每个 Flask 会话存储大数据或服务连接

Store large data or a service connection per Flask session

我正在编写一个小型 Flask 应用程序,并使用 pyRserve 将其连接到 Rserve。我希望每个会话都启动并保持其自己的 Rserve 连接。

像这样:

session['my_connection'] = pyRserve.connect()

不起作用,因为连接对象不是 JSON 可序列化的。另一方面,是这样的:

flask.g.my_connection = pyRserve.connect()

不起作用,因为它不会在请求之间持续存在。更困难的是,pyRserve 似乎没有为连接提供任何标识符,因此我无法在会话中存储连接 ID 并在每次请求之前使用它来检索正确的连接。

有没有办法实现每个会话的唯一连接?

以下内容适用于您不想为每个请求重新创建的任何全局 Python 数据,不仅是 rserve,而且不仅仅是每个用户唯一的数据。

我们需要一些公共位置来为每个用户创建一个 rserve 连接。最简单的方法是将 运行 一个 multiprocessing.Manager 作为一个单独的进程。

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 会做的)。这最终使 rserve 连接对每个用户都是唯一的,而不是每个会话。

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')

这应该可以帮助您入门,但还有很多可以改进的地方,例如不对地址和密码进行硬编码,以及不丢弃与管理器的连接。这是用 Python 3 编写的,但是 应该 与 Python 2.

一起使用