在多线程sqlalchemy Web应用程序中,建议的scoped_session使用模式是什么? [英] What's the recommended scoped_session usage pattern in a multithreaded sqlalchemy webapp?

查看:70
本文介绍了在多线程sqlalchemy Web应用程序中,建议的scoped_session使用模式是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用python和sqlalchemy-0.7编写应用程序.它首先初始化sqlalchemy orm(使用声明式),然后启动多线程Web服务器-我目前正在使用web.py进行快速原型制作,但是将来可能会改变.我还将为计划的作业添加其他线程",以此类推,可能还会使用其他python线程.

I'm writing an application with python and sqlalchemy-0.7. It starts by initializing the sqlalchemy orm (using declarative) and then it starts a multithreaded web server - I'm currently using web.py for rapid prototyping but that could change in the future. I will also add other "threads" for scheduled jobs and so on, probably using other python threads.

从SA文档中,我了解到必须使用scoped_session()来获取线程本地会话,因此我的web.py应用程序最终应类似于:

From SA documentation I understand I have to use scoped_session() to get a thread-local session, so my web.py app should end up looking something like:

import web
from myapp.model import Session  # scoped_session(sessionmaker(bind=engine))
from myapp.model import This, That, AndSoOn
urls = blah...
app  = web.application(urls, globals())

class index:
    def GET(self):
        s = Session()
        # get stuff done
        Session().remove()
        return(stuff)

class foo:
    def GET(self):
        s = Session()
        # get stuff done
        Session().remove()
        return(stuff)

这是处理会话的正确方法吗?

Is that the Right Way to handle the session?

据我了解,我应该在每个方法上都获得一个scoped_session,因为它将为我提供一个我无法预先获得的线程本地会话(例如在模块级别).

As far as I understand, I should get a scoped_session at every method since it'll give me a thread local session that I could not obtain beforehand (like at the module level).

此外,我应该致电.remove()或.commit()或

Also, I should call .remove() or .commit() or something like them at every method end, otherwise the session will still contain Persistent objects and I would not be able to query/access the same objects in other threads?

如果该模式是正确的,则可以通过只编写一次(也许使用装饰器)将其改进为更好的模式?这样的装饰器可以获取会话,调用该方法,然后确保正确处置该会话.它将如何将会话传递给装饰的函数?

If that pattern is the correct one, it could probably be made better by writing it only once, maybe using a decorator? Such a decorator could get the session, invoke the method and then make sure to dispose the session properly. How would that pass the session to the decorated function?

推荐答案

是的,这是正确的方法.

Yes, this is the right way.

示例:

带有烧瓶微框架-SQLAlchemy/"rel =" nofollow noreferrer> Flask-sqlalchemy 扩展会执行您所描述的操作.它还在每个HTTP请求("view"功能)结束时自动执行.remove(),因此会话由当前线程释放.仅调用.commit()是不够的,您应该使用.remove().

The Flask microframework with Flask-sqlalchemy extension does what you described. It also does .remove() automatically at the end of each HTTP request ("view" functions), so the session is released by the current thread. Calling just .commit() is not sufficient, you should use .remove().

当不使用Flask视图时,我通常使用"with"语句:

When not using Flask views, I usually use a "with" statement:

@contextmanager
def get_db_session():
    try:
        yield session
    finally:
        session.remove()

with get_db_session() as session:
    # do something with session

您可以创建类似的装饰器.

You can create a similar decorator.

作用域会话会创建一个DBMS连接池,因此,此方法比在每个HTTP请求中打开/关闭会话要快.它也可以与greenlets(gevent或eventlet)配合使用.

Scoped session creates a DBMS connection pool, so this approach will be faster than opening/closing session at each HTTP request. It also works nice with greenlets (gevent or eventlet).

这篇关于在多线程sqlalchemy Web应用程序中,建议的scoped_session使用模式是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆