2015-02-10 54 views
1

我正在编写一个小Flask应用程序,并使用pyRserve连接到Rserve。我希望每个会话都能启动并维护自己的Rserve连接。每个会话如何存储独特的Rserve连接?

事情是这样的:

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

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

flask.g.my_connection = pyRserve.connect() 

不起作用,因为它不会在请求之间持续存在。为了增加难度,pyRserve似乎没有为连接提供任何标识符,所以我不能在会话中存储连接ID,并使用它在每个请求之前检索正确的连接。

有没有一种方法可以完成每个会话的独特连接?

+0

为什么你需要为一个会话使用相同的连接? – dirn 2015-02-10 02:40:09

+0

因为我需要R名称空间中的对象在会话期间为同一用户保留(但对其他用户不可见/可访问)。例如,用户可以加载一些数据并适合模型 - 我希望能够在其他页面上访问该模型(不需要重新设置)(即在其他页面发出请求之后)。 – izyda 2015-02-10 05:39:21

+0

我明白了。我不确定我真的需要每个用户都有一个可重用的连接。我唯一的要求是用户的R连接/会话能够访问使用该用户先前请求创建的R对象。我想一个可行的解决方案可能是有一个R连接将当前R工作区保存到服务器,将该工作区的ID保存为一个cookie,并且在新的请求时,有一个新的R连接读取该工作区返回... – izyda 2015-02-10 06:35:45

回答

4

我们需要一些公共位置为每个用户创建一个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一起工作。