Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 什么';在多线程sqlalchemy webapp中,推荐的作用域_会话使用模式是什么?_Python_Multithreading_Session_Sqlalchemy - Fatal编程技术网

Python 什么';在多线程sqlalchemy webapp中,推荐的作用域_会话使用模式是什么?

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

我正在用python和sqlalchemy-0.7编写一个应用程序。它首先初始化sqlalchemy orm(使用声明性),然后启动一个多线程web服务器——我目前正在使用web.py进行快速原型制作,但将来可能会发生变化。我还将为计划作业等添加其他“线程”,可能使用其他python线程

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

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()