【发布时间】:2012-09-12 15:24:51
【问题描述】:
Python 是否有会话功能?
如果是,那么我该如何使用它以及我应该使用哪个库?
【问题讨论】:
-
您是在询问 Web 框架吗?您使用的是哪个网络框架? Python 有几十个。
Python 是否有会话功能?
如果是,那么我该如何使用它以及我应该使用哪个库?
【问题讨论】:
这可能是一个老问题,但我遇到了同样的问题,即 Python 中没有内置的会话支持。我写了一个简单的会话处理程序,可能对某人有用:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import tempfile
import hashlib
import os
import time
import random
import errno
import ast
import pprint
import fcntl
class CGISession:
__sessionfile = ''
__newid = ''
__date = ''
__tmp = ''
__pid = ''
__time = ''
__rand = ''
__pp = pprint.PrettyPrinter()
__fs = ''
def __init__(
self,
id=None,
directory=None,
hash='md5',
):
if directory is None:
self.__directory = tempfile.gettempdir()
else:
if not os.path.exists(directory):
try:
os.makedirs(directory)
except OSError, error:
if error.errno != errno.EEXIST:
raise
self.__directory = directory
if hash not in ['md5', 'sha256', 'sha512']:
self.__hash = 'md5'
else:
self.__hash = hash
if id is None:
self.__id = self.__genSessionID()
self.__fs = open(os.path.join(self.__directory,
'pycgiession_{0}'.format(self.__id)), 'w')
fcntl.flock(self.__fs.fileno(), fcntl.LOCK_EX)
self.__fs.write('{}')
self.__fs.close()
self.__sessionfile = os.path.join(self.__directory,
'pycgiession_{0}'.format(self.__id))
os.chmod(self.__sessionfile, 0640)
else:
try:
open(os.path.join(self.__directory,
'pycgiession_{0}'.format(os.path.basename(id))),
'r').close()
self.__id = os.path.basename(id)
self.__sessionfile = os.path.join(self.__directory,
'pycgiession_{0}'.format(self.__id))
os.chmod(self.__sessionfile, 0640)
except IOError, error:
if error.errno == errno.ENOENT:
self.__id = self.__genSessionID()
self.__fs = open(os.path.join(self.__directory,
'pycgiession_{0}'.format(self.__id)), 'w')
fcntl.flock(self.__fs.fileno(), fcntl.LOCK_EX)
self.__fs.write('{}')
self.__fs.close()
self.__sessionfile = os.path.join(self.__directory,
'pycgiession_{0}'.format(self.__id))
os.chmod(self.__sessionfile, 0640)
else:
raise
def __genSessionID(self):
self.__pid = str(os.getpid())
self.__time = ''.join(map(str, time.gmtime()[0:]))
self.__rand = str(random.random())
if self.__hash == 'sha256':
sha256 = hashlib.sha256()
sha256.update(self.__pid)
sha256.update(self.__time)
sha256.update(self.__rand)
self.__newid = sha256.hexdigest()
elif self.__hash == 'sha512':
sha512 = hashlib.sha512()
sha512.update(self.__pid)
sha512.update(self.__time)
sha512.update(self.__rand)
self.__newid = sha512.hexdigest()
else:
md5 = hashlib.md5()
md5.update(self.__pid)
md5.update(self.__time)
md5.update(self.__rand)
self.__newid = md5.hexdigest()
return self.__newid
def getID(self):
return self.__id
def setParam(self, key, value):
self.__fs = open(self.__sessionfile, 'r')
fcntl.flock(self.__fs.fileno(), fcntl.LOCK_EX)
self.__date = self.__fs.readlines()
self.__fs.close()
self.__fs = open(self.__sessionfile, 'w')
fcntl.flock(self.__fs.fileno(), fcntl.LOCK_EX)
self.__date = ast.literal_eval(self.__date[0])
self.__date[key] = value
self.__fs.write(self.__pp.pformat(self.__date))
self.__fs.close()
def getParam(self, key):
self.__fs = open(self.__sessionfile, 'r')
fcntl.flock(self.__fs.fileno(), fcntl.LOCK_EX)
self.__date = self.__fs.readline()
self.__fs.close()
self.__date = ast.literal_eval(self.__date)
try:
self.__date = self.__date[key]
return self.__date
except KeyError:
return None
def getAll(self):
self.__fs = open(self.__sessionfile, 'r')
fcntl.flock(self.__fs.fileno(), fcntl.LOCK_EX)
self.__date = self.__fs.readlines()
self.__fs.close()
self.__date = ast.literal_eval(self.__date[0])
return self.__date
def delParam(self, key):
self.__fs = open(self.__sessionfile, 'r')
fcntl.flock(self.__fs.fileno(), fcntl.LOCK_EX)
self.__date = self.__fs.readlines()
self.__fs.close()
self.__fs = open(self.__sessionfile, 'w')
fcntl.flock(self.__fs.fileno(), fcntl.LOCK_EX)
self.__date = ast.literal_eval(self.__date[0])
try:
del self.__date[key]
except KeyError:
pass
self.__fs.write(self.__pp.pformat(self.__date))
self.__fs.close()
def clear(self):
self.__fs = open(self.__sessionfile, 'w')
fcntl.flock(self.__fs.fileno(), fcntl.LOCK_EX)
self.__fs.write('{}')
self.__fs.close()
def delete(self):
os.remove(self.__sessionfile)
例子:
>>> from CGISession import CGISession
>>> session = CGISession()
>>>
>>> session.getID()
'7e487c3c300126fddbecb37b041d66e3'
>>>
>>> session.setParam('name','A')
>>> session.setParam('friends',['C','D','E'])
>>>
>>> session.getParam('name')
'A'
>>> session.getParam('friends')
['C', 'D', 'E']
>>>
>>> session.delParam('name')
>>> session.delParam('friends')
>>>
>>> session.getParam('name')
>>> session.delParam('friends')
>>>
>>> session.delete()
>>>
【讨论】:
一些 Python Web 框架确实提供了“会话”的概念。 (当然,Python 语言本身与它无关!-)。
例如Beaker是一个优秀的支持会话的轻量级WSGI中间件;由于 WSGI 通常是将任何 Python Web 框架与任何 Web 服务器连接起来的最佳方式,当然您总是可以在 WSGI 事务中插入 WSGI 中间件,因此 Beaker(与任何其他 WSGI 中间件一样)非常适用。
【讨论】:
mod_python 好得多:它不会将您绑定到单个 Web 服务器,并允许您“插入”许多有用的中间件模块——包括关于身份验证的模块以及其他关于会话的人; 非常模块化和灵活——您仍然可以完全独立地选择您喜欢的服务器和什么框架。
Beaker 在依赖 WSGI 的 Python Web 应用程序中非常流行,但您必须了解 Python 是一种通用编程语言,它不像 PHP 那样 100% 面向 Web。
如果您列出有关您需要的应用程序的更多信息也会有所帮助。
【讨论】: