Python SQLAlchemy+;Tornado:如何为SQLAlchemy创建scopefunc';什么是范围会话?
使用tornado,我想创建一点中间件魔法,确保我的SQLAlchemy会话得到正确关闭/清理,这样就不会在一个请求到下一个请求之间共享对象。诀窍在于,由于我的一些tornado处理程序是异步的,所以我不能只为每个请求共享一个会话 因此,我只能尝试创建一个ScopedSession,它知道如何为每个请求创建一个新会话。我所需要做的就是为我的代码定义一个scopefunc,它可以将当前执行的请求转换为某种类型的唯一键,但是我似乎不知道如何在任何时间点获取当前请求(在当前RequestHandler的范围之外,我的函数也无权访问)Python SQLAlchemy+;Tornado:如何为SQLAlchemy创建scopefunc';什么是范围会话?,python,sqlalchemy,tornado,Python,Sqlalchemy,Tornado,使用tornado,我想创建一点中间件魔法,确保我的SQLAlchemy会话得到正确关闭/清理,这样就不会在一个请求到下一个请求之间共享对象。诀窍在于,由于我的一些tornado处理程序是异步的,所以我不能只为每个请求共享一个会话 因此,我只能尝试创建一个ScopedSession,它知道如何为每个请求创建一个新会话。我所需要做的就是为我的代码定义一个scopefunc,它可以将当前执行的请求转换为某种类型的唯一键,但是我似乎不知道如何在任何时间点获取当前请求(在当前RequestHandler
有什么我可以做的吗?您可能希望将
会话
与请求本身相关联(即,如果不方便,不要使用scopedsession)。然后你可以说,request.session
。仍然需要在开始/结束处设置挂钩,以便进行安装/拆卸
编辑:自定义作用域函数
def get_current_tornado_request():
# TODO: ask on the Tornado mailing list how
# to acquire the request currently being invoked
Session = scoped_session(sessionmaker(), scopefunc=get_current_tornado_request)
(这是2017年对2011年一个问题的回答)正如@Stefano Borini所指出的,在Tornado 4中最简单的方法就是隐式地让RequestHandler。Tornado将在使用协同路由装饰器模式时跟踪处理程序实例状态:
import logging
_logger = logging.getLogger(__name__)
from sqlalchemy import create_engine, exc as sqla_exc
from sqlalchemy.orm import sessionmaker, exc as orm_exc
from tornado import gen
from tornado.web import RequestHandler
from my_models import SQLA_Class
Session = sessionmaker(bind=create_engine(...))
class BaseHandler(RequestHandler):
@gen.coroutine
def prepare():
self.db_session = Session()
def on_finish():
self.db_session.close()
class MyHander(BaseHandler):
@gen.coroutine
def post():
SQLA_Object = self.db_session.query(SQLA_Class)...
SQLA_Object.attribute = ...
try:
db_session.commit()
except sqla_exc.SQLAlchemyError:
_logger.exception("Couldn't commit")
db_session.rollback()
如果你真的需要异步引用一个SQL炼金术会话,它是在<代码>声明基础> /COD>(我将考虑反模式,因为它将模型与应用程序过度耦合),Amit Matani有一个不起作用的示例。
我根本不知道tornado,但您可能希望将会话与请求本身关联起来(即,如果不方便,不要使用scopedsession)。然后你可以说request.session。仍然需要在安装/拆卸的开始/结束处有挂钩。@zzzeek如果您将此作为答案发布,我会将其标记为正确!我想得越多,就越意识到你是对的——这是最快、最容易理解的获得我需要的东西的方法。谢谢我也这么认为,在所有异步处理程序之间共享通过scopped_会话创建的会话会造成不一致,对吗?假设在一个处理程序中,我可以在处理程序末尾调用scopped_session.remove(),但其他处理程序(异步运行)可能仍在使用它!因此,基本上我需要做的是在请求开始时创建一个会话,并将其分配给请求处理程序。但是我需要调用许多需要会话的方法,我需要在它们之间传递请求处理程序或会话本身。。。代码变得难看:(然后将scopedsession与自定义作用域函数一起使用。您能解释一下如何编写自定义作用域函数吗…谢谢。我是PythontorAndo(或您的应用程序)的新手,需要提供一些函数,当不带参数调用时,返回正在服务的当前请求。然后将其传递给“scopefunc”。请参见上面的编辑。我不明白,为什么不能在prepare()中启动会话?