I think this script should now be functional enough to post here at ActiveState. When you reply or vote down, please post some information on your problem with the code, and if you can, maybe something about the solution. This interface works, and is designed especially for Python. If you like it, don't be afraid to post that either, constructive criticism is all good, but compliments are even better! ;)
Get the latest version of this code here: http://wiki.sunjay.ca/Python:Contents/Python_Session
Latest Changes:
- Added a new function for making the session cookie last longer. See code for
set_expires
. Note: This new function is just in case you need to include a session for longer than one brower session (for example, one day instead).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 | #!/usr/local/bin/python26
"""
Python Session Handling
Note: A user must have cookies enabled!
TODO:
* Support Named Sessions
Copyright 2010 - Sunjay Varma
Latest Version: http://www.sunjay.ca/download/session.py
"""
import cgi
import os
import time
import errno
import hashlib
import datetime
from Cookie import SimpleCookie
from cPickle import dump, load, HIGHEST_PROTOCOL, dumps, loads
if not "HTTP_COOKIE" in os.environ:
os.environ["HTTP_COOKIE"] = ""
SESSION = None
S_DIR = os.path.expanduser("~/.py_sessions") # expanduser for windows users
S_EXT = ".ps"
S_ID = "__sid__"
TODAY = str(datetime.date.today())
DEBUG = [] # debug messages
if not os.path.exists(S_DIR):
os.makedirs(S_DIR)
class NoCookiesError(Exception): pass
class NotStarted(Exception): pass
class Session(object):
def __init__(self):
self.data = {}
self.started = False
self._flock = None
self.expires = 0 # delete right away
self.__sid = sid = self.__getsid()
self.path = os.path.join(S_DIR, sid+S_EXT)
def isset(self, name):
"""Is the variable set in the session?"""
if not self.started:
raise NotStarted("Session must be started")
return name in self
def unset(self, name):
"""Unset the name from the session"""
if not self.started:
raise NotStarted("Session must be started")
del self[name]
@staticmethod
def __newsid():
"""Create a new session ID"""
h = hashlib.new("ripemd160")
h.update(str(time.time()/time.clock()**-1)+str(os.getpid()))
return h.hexdigest()
def __getsid(self):
"""Get the current session ID or return a new one"""
# first, try to load the sid from the GET or POST forms
form = cgi.FieldStorage()
if form.has_key(S_ID):
sid = form[S_ID].value
return sid
# then try to load the sid from the HTTP cookie
self.cookie = SimpleCookie()
if os.environ.has_key('HTTP_COOKIE'):
self.cookie.load(os.environ['HTTP_COOKIE'])
if S_ID in self.cookie:
sid = self.cookie[S_ID].value
return sid
else:
raise NoCookiesError("Could not find any cookies")
# if all else fails, return a new sid
return self.__newsid()
def getsid(self):
"""
Return the name and value that the sid needs to have in a GET or POST
request
"""
if not self.started:
raise NotStarted("Session must be started")
return (S_ID, self.__sid)
def start(self):
"""Start the session"""
if self.started:
return True # session cannot be started more than once per script
self._flock = FileLock(self.path)
self._flock.acquire()
# load the session if it exists
if os.path.exists(self.path):
with open(self.path, "rb") as f:
self.data = dict(load(f))
self.data["__date_loaded__"] = TODAY
else: # create a session
with open(self.path, "wb") as f:
self.data = {"__date_loaded__":TODAY}
# the session is officially started!
self.started = True
# store the sid in the cookie
self.cookie[S_ID] = self.__sid
self.cookie[S_ID]["expires"] = str(self.expires)
self.cookie[S_ID]["version"] = "1"
return True
def commit(self):
"""Commit the changes to the session"""
if not self.started:
raise NotStarted("Session must be started")
with open(self.path, "wb") as f:
dump(self.data, f, HIGHEST_PROTOCOL)
def destroy(self):
"""Destroy the session"""
if not self.started:
raise NotStarted("Session must be started")
os.delete(self.path)
if self._flock:
self._flock.release()
self.started = False
def output(self):
"""Commit changes and send headers."""
if not self.started:
raise NotStarted("Session must be started")
self.commit()
return self.cookie.output()
def setdefault(self, item, default=None):
if not self.started:
raise NotStarted("Session must be started")
if not self.isset(item):
self[item] = default
return self[item]
def set_expires(self, days):
"""Sets the expiration of the cookie"""
date = datetime.date.today() + datetime.timedelta(days=days)
self.expires = date.strftime("%a, %d-%b-%Y %H:%M:%S PST")
self.cookie[S_ID]["expires"] = str(self.expires)
def __getitem__(self, item):
"""Get the item from the session"""
if not self.started:
raise NotStarted("Session must be started")
return self.data.__getitem__(item)
def __setitem__(self, item, value):
"""set the item into the session"""
if not self.started:
raise NotStarted("Session must be started")
self.data.__setitem__(item, value)
def __delitem__(self, item):
if not self.started:
raise NotStarted("Session must be started")
self.data.__delitem__(item)
def __contains__(self, item):
"""Return if item in the session"""
if not self.started:
raise NotStarted("Session must be started")
return self.data.__contains__(item)
def __iter__(self):
"""Go through the names of all the session variables"""
if not self.started:
raise NotStarted("Session must be started")
return self.data.__iter__()
def start():
global SESSION
SESSION = Session()
return SESSION.start()
def destroy():
global SESSION
if SESSION:
SESSION.destroy()
def get_session():
global SESSION
if not SESSION:
SESSION = Session()
return SESSION
### The following is a (little) modified version of this:
# http://www.evanfosmark.com/2009/01/cross-platform-file-locking-support-in-
# python/
class FileLockException(Exception):
pass
class FileLock(object):
""" A file locking mechanism that has context-manager support so
you can use it in a with statement. This should be relatively cross
compatible as it doesn't rely on msvcrt or fcntl for the locking.
"""
def __init__(self, file_name, timeout=10, delay=.05):
""" Prepare the file locker. Specify the file to lock and optionally
the maximum timeout and the delay between each attempt to lock.
"""
self.is_locked = False
self.lockfile = os.path.join(os.getcwd(), "%s.lock" % file_name)
self.file_name = file_name
self.timeout = timeout
self.delay = delay
def acquire(self):
""" Acquire the lock, if possible. If the lock is in use, it check again
every `wait` seconds. It does this until it either gets the lock or
exceeds `timeout` number of seconds, in which case it throws
an exception.
"""
if self.is_locked:
return
start_time = time.time()
while True:
try:
self.fd = os.open(self.lockfile, os.O_CREAT|os.O_EXCL|os.O_RDWR)
break;
except OSError as e:
if e.errno != errno.EEXIST:
raise
if (time.time() - start_time) >= self.timeout:
raise FileLockException("Timeout occured.")
time.sleep(self.delay)
self.is_locked = True
def release(self):
""" Get rid of the lock by deleting the lockfile.
When working in a `with` statement, this gets automatically
called at the end.
"""
if self.is_locked:
os.close(self.fd)
os.unlink(self.lockfile)
self.is_locked = False
def __enter__(self):
""" Activated when used in the with statement.
Should automatically acquire a lock to be used in the with block.
"""
if not self.is_locked:
self.acquire()
return self
def __exit__(self, type, value, traceback):
""" Activated at the end of the with statement.
It automatically releases the lock if it isn't locked.
"""
if self.is_locked:
self.release()
def __del__(self):
""" Make sure that the FileLock instance doesn't leave a lockfile
lying around.
"""
self.release()
def print_session(session):
"""
Prints info from the current session.
WARNING: ONLY FOR DEBUGGING. MAJOR SECURITY RISK!
"""
print "<h3>Session Data</h3>"
print "<dl>"
for name in session:
print "<dt>%s <i>%s</i></dt>"%(name, type(session[name]))
print "<dd>%s</dd>"%repr(session[name])
print "</dl>"
def main():
"""Tester Program"""
start() # session.start()
if SESSION.isset("views"):
SESSION["views"] += 1
else:
SESSION["views"] = 1
print "Content-type: text/html"
print SESSION.output()
print
print "<html><head><title>Session Testing</title></head><body>"
print "<h2>You have viewed this page %i times.</h2>"%SESSION["views"]
print_session(SESSION)
print "<p>", SESSION.path, "</p>"
for line in DEBUG:
print "<p>%s</p>"%line
print "<p>%s</p>"%SESSION.data
print "</body></html>"
if __name__ == "__main__":
main()
|
There can be some security leaks, but depending on your server, and other things, it should work quite well.
If the client does not have cookies enabled, you may need to pass some query parameters in every single time, or keep track of the session id some other way.
You can get the session id through the getsid
method of the session object.
I tried to imitate the PHP session interface as much as possible, although I did add some Python specialties as well.
The setdefault
method, was an idea that I stole from Python's dict
object.
Of course, with my lack of PHP knowledge, I cannot say that I completely copied the Session interface. There may be things that I missed. Still consider this though, I was only going for basing this on PHP (even though I may sometimes say otherwise) this is not meant to copy the interface, only give some way into managing it through Python.
For an example on how to use this, go to http://wiki.sunjay.ca/Python:Contents/Python_Session#Examples
Good but IE not run :)
how can i make it work in IE
Hi I have been trying to download an image from website (no username and password required) but every time I am getting an empty file. I have used conventional urllib .retrieve and requests methodologies but getting the same result. One thing more is that if I try to open the same image manually by copy pasting the URL after 15-20 min then that image itself does not open. I am assuming that some sort of session handling is required in this case . Below is my code which returns me empty image.
def savePic(url): uri="C:\Python27\Scripts\Photosurl2.jpg" if url!="": urllib.urlretrieve(url, uri)
savePic("http://www-nass.nhtsa.dot.gov/nass/cds/GetBinary.aspx?ImageView&ImageID=491410290&Desc=Lookback+from+final+rest&Title=Scene+Photos+-+image1&Version=1&Extend=jpg")
Any help is appreciated.