Python 什么';在多线程sqlalchemy webapp中,推荐的作用域_会话使用模式是什么?
我正在用python和sqlalchemy-0.7编写一个应用程序。它首先初始化sqlalchemy orm(使用声明性),然后启动一个多线程web服务器——我目前正在使用web.py进行快速原型制作,但将来可能会发生变化。我还将为计划作业等添加其他“线程”,可能使用其他python线程 从SA文档中,我了解到我必须使用scoped_session()来获取线程本地会话,因此我的web.py应用程序最终应该看起来像:Python 什么';在多线程sqlalchemy webapp中,推荐的作用域_会话使用模式是什么?,python,multithreading,session,sqlalchemy,Python,Multithreading,Session,Sqlalchemy,我正在用python和sqlalchemy-0.7编写一个应用程序。它首先初始化sqlalchemy orm(使用声明性),然后启动一个多线程web服务器——我目前正在使用web.py进行快速原型制作,但将来可能会发生变化。我还将为计划作业等添加其他“线程”,可能使用其他python线程 从SA文档中,我了解到我必须使用scoped_session()来获取线程本地会话,因此我的web.py应用程序最终应该看起来像: import web from myapp.model import Sess
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)
这是处理会话的正确方法吗
据我所知,我应该在每个方法上都获得一个作用域_会话,因为它会给我一个线程本地会话,而我事先无法获得(比如在模块级别)
另外,我应该调用.remove()或.commit(),或者在每个方法结束时调用,否则会话仍将包含对象,并且我将无法在其他线程中查询/访问相同的对象
如果这个模式是正确的,那么只需编写一次就可以做得更好,也许可以使用装饰器?这样的装饰器可以获取会话,调用方法,然后确保正确地处理会话。如何将会话传递给修饰函数?如果为每个请求创建新会话,并且每个请求都由单个线程处理,则不需要创建作用域会话 您必须调用
s.commit()
使挂起的对象持久化,即将更改保存到数据库中
您可能还想通过调用
s.close()
来关闭会话。是的,这是正确的方法
例如:
带扩展的微框架与您描述的一样。它还会在每个HTTP请求结束时自动执行.remove()(“查看”函数),因此会话由当前线程释放。仅调用.commit()是不够的,应该使用.remove()
不使用Flask视图时,我通常使用“with”语句:
@contextmanager
def get_db_session():
try:
yield session
finally:
session.remove()
with get_db_session() as session:
# do something with session
您可以创建一个类似的装饰器
作用域会话创建一个DBMS连接池,因此这种方法比在每个HTTP请求时打开/关闭会话要快。它也适用于greenlet(gevent或eventlet)。据我所知,我确实必须使用作用域会话,因为SQLAlchemy不允许我在多个打开的事务(会话)中拥有相同的对象:如果我尝试,我只会收到类似“SQLAlchemy.exc.InvalidRequestError:object FOO已附加到会话“1234”(这是“5678”)的错误。”我看到在
commit
和rollback
中调用了close
。您确定它是Session().remove()
而不是Session.remove()
?谢谢您的想法,但是会话变量的类型是什么?是sqlalchemy.orm.scoping.scoped_会话还是sqlalchemy.orm.session.session(在这种情况下,您什么时候使用scoped_会话)?我认为这个例子应该是使用get_db_session()作为会话的,或者您不能使用会话。flask_sqlalchemy
基本上就是这样做的。在应用程序上下文拆卸时(shutdown\u session()
,从内部SQLAlchemy.init\u app
),如果请求,应用程序将自动提交会话,然后将其删除。然后,您的会话上下文可以有一个附加参数,autocommit=False
,并在删除会话之前具有if autocommit:session.commit()
。