Sqlalchemy中的scoped_session(..)和scoped_session(..)()之间的区别

5
使用 scoped_session 和直接使用 Session 对象的区别是什么?
engine = create_engine(url)
session = scoped_session(sessionmaker(bind=engine))

session.add(..)
session.commit()
session.remove()

session.add(..)
session.commit()
session.remove()

创建scoped_session对象的实例:

engine = create_engine(url)
session = scoped_session(sessionmaker(bind=engine))

session().add(..)
session().commit()
session.remove()

session().add(..)
session().commit()
session.remove()

通过调用session(),Sqlalchemy总是为相同的线程返回相同的会话:

>> session() is session() 
True
>> session is session() 
False

在多线程环境中操作连接的方式是否正确?如果是,为什么SQLAlchemy允许使用session而不是session()进行查询?

1个回答

6
"scoped_session"返回一个工厂对象,所以你必须调用工厂来返回一个实例。在几乎所有的情况下, "scoped_session"会在相同作用域中被调用时返回相同的会话(在大多数用例中,该作用域是针对网页上的单个用户请求)。
因此,尽管您重复调用session(),但它实际上并没有创建多个会话,而是每次都返回相同的会话。
建议使用大写字母"S"来表示session是一个工厂而不是对象的实例。
更多文档内容请参见: http://docs.sqlalchemy.org/en/latest/orm/contextual.html 编辑:两种方法都将访问相同的对象。我始终发现从scoped_session生成一个实例更清晰(不是所有工厂都提供这样的功能),但两者都将访问本地线程会话对象。
更多信息请参见:http://docs.sqlalchemy.org/en/latest/orm/contextual.html#implicit-method-access

注意术语的使用。在Python中,生成器是一个非常具体的东西;你所说的应该是“工厂”。 - univerio
"scoped_session" 返回一个生成器对象,因此您必须调用生成器才能返回一个实例。最好的部分是我不必这样做,因为两者都可以工作:Session.commit()Session().commit()。问题是,有什么区别吗?也许 Session().commit() 在多线程中起作用,而 Session.commit() 不起作用? - User
2
更新了我的回答。基本上,工厂会自动返回适当的线程本地会话。我觉得这个功能不太清楚,但每个人都有自己的看法。 - ApolloFortyNine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接