我正在写一个小烧瓶应用程序,并让它连接到使用pyR服务。我希望每个会话都启动,然后保持自己的服务器连接。
大概是这样的:
session['my_connection'] = pyRserve.connect()
无法工作,因为连接对象不可JSON序列化。另一方面,类似这样的情况:
flask.g.my_connection = pyRserve.connect()
不起作用,因为它不会在请求之间持久化。更困难的是,pyRserve似乎没有为连接提供任何标识符,因此我无法在会话中存储连接ID,并在每次请求之前使用该ID检索正确的连接。
有没有一种方法可以实现每个会话具有唯一的连接?
以下内容适用于您不希望为每个请求重新创建的任何全局Python数据,而不仅仅是rserve,也不仅仅是每个用户独有的数据。
我们需要一些公共的位置来为每个用户创建一个固定的连接。最简单的方法是运行多重处理。管理器
作为一个单独的进程。
import atexit
from multiprocessing import Lock
from multiprocessing.managers import BaseManager
import pyRserve
connections = {}
lock = Lock()
def get_connection(user_id):
with lock:
if user_id not in connections:
connections[user_id] = pyRserve.connect()
return connections[user_id]
@atexit.register
def close_connections():
for connection in connections.values():
connection.close()
manager = BaseManager(('', 37844), b'password')
manager.register('get_connection', get_connection)
server = manager.get_server()
server.serve_forever()
在启动应用程序之前运行它,以便管理器可以:
python rserve_manager.py
我们可以使用一个简单的函数在请求期间从应用程序访问此管理器。这假设会话中的user_id有一个值(例如,这就是Flask-Login所做的)。这最终会使得每个用户而不是每个会话的rserver连接都是唯一的。
from multiprocessing.managers import BaseManager
from flask import g, session
def get_rserve():
if not hasattr(g, 'rserve'):
manager = BaseManager(('', 37844), b'password')
manager.register('get_connection')
manager.connect()
g.rserve = manager.get_connection(session['user_id'])
return g.rserve
在视图中访问它:
result = get_rserve().eval('3 + 5')
这应该可以让你开始,尽管还有很多可以改进的地方,比如不硬编码地址和密码,不丢弃与管理器的连接。这是用Python3编写的,但应该可以用Python2。