2015-02-10 3 views
1

Я пишу небольшое приложение для фляшек и подключаюсь к Rserve с помощью pyRserve. Я хочу, чтобы каждый сеанс инициировал, а затем поддерживал его собственное соединение Rserve.Как можно сохранить уникальное соединение Rserve за сеанс?

Что-то вроде этого:

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

не работает, потому что объект соединения не JSON сериализации. С другой стороны, что-то вроде этого:

flask.g.my_connection = pyRserve.connect() 

не работает, потому что он не сохраняется между запросами. Чтобы добавить к сложности, похоже, что pyRserve не предоставляет идентификатор для соединения, поэтому я не могу сохранить идентификатор соединения в сеансе и использовать его для получения правильного соединения перед каждым запросом.

Есть ли способ совершить уникальное соединение за сеанс?

+0

Зачем вам нужно использовать одно и то же соединение для сеанса? – dirn

+0

Поскольку мне нужно, чтобы объекты в пространстве имен R сохранялись для одного и того же пользователя во время сеанса (но не были видимыми/доступными для других пользователей). Например, пользователь может загружать некоторые данные и подгонять модель - я хочу иметь возможность получить доступ к этой модели (не переустанавливая ее) на других страницах (т. Е. После того, как были сделаны другие запросы к Flask). – izyda

+0

Я вижу. Я не уверен, что мне действительно нужно повторное использование для каждого пользователя. Моим единственным требованием является то, что соединение/сеанс пользователя R может иметь доступ к объектам R, созданным с использованием предыдущих запросов этого пользователя. Я полагаю, что подходящее решение может состоять в том, чтобы иметь R-соединение, сохраняя текущее рабочее пространство R на сервере, сохраняя идентификатор этой рабочей области в качестве файла cookie, и по новому запросу новые R-соединения считывают это рабочее пространство ... – izyda

ответ

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). Это в конечном итоге делает уникальное соединение уникальным для каждого пользователя, а не за сеанс.

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.

Смежные вопросы