如何关闭SQLAlchemy会话?


71

遵循我们在如何关闭MySQL中的sqlalchemy连接中的评论之后,我正在检查SQLAlchemy创建到我的数据库中的连接,如果不退出Python,我将无法关闭它们。

如果我在python控制台中运行此代码,它将保持会话打开状态,直到我退出python为止:

from sqlalchemy.orm import sessionmaker
from models import OneTable, get_engine

engine = get_engine(database="mydb")
session = sessionmaker(bind=engine)()

results = session.query(OneTable.company_name).all()

# some work with the data #

session.close()

我发现要关闭它的唯一解决方法是engine.dispose()在最后调用。

根据我上面给出的链接中的评论,我的问题现在是:

  • 为什么engine.dispose()需要关闭会议?
  • session.close()不够吗

1
使用sqlalchemy.pool.NullPool不能解决您的问题?
Alvaro Fuentes 2014年


执行查询AccessShareLock后如何清除postgres关系select
新手

Answers:


87

对于“会话”一词,这里有一个主要的困惑。我不确定在这里,但似乎您可能将SQLAlchemy会话MySQL @@ session混淆了,后者指的是您首次建立与MySQL的连接以及断开连接时的范围。

这两个概念并不相同。SQLAlchemy会话通常表示一个或多个事务的范围特定数据库连接后。

因此,从字面上看,您的问题的答案是调用session.close(),即“如何正确关闭SQLAlchemy会话”。

但是,问题的其余部分表明您希望某些功能,当Session关闭某个特定功能时,您也希望实际的DBAPI连接也要关闭。

这基本上意味着您希望禁用连接池。正如其他答案所提到的那样,很容易使用NullPool


7
这完全做到了。通过指出,我注意到我混合了SQLAlchemy和MySQL会话。现在,get_engine(database="mydb", poolclass=NullPool)一旦我关闭它,它就会关闭session.close()。非常感谢!
fedorqui'SO停止伤害

我想由于会话未正确关闭而出现问题。我的api给我随机的行数。例如,我的表(mysql)中有10行。当我点击我的api时,我得到10、0、9等结果。PS我使用sqlalchemy(不是烧瓶sqlalchemy)。请指导我。
侯赛因,2015年

72

session.close() 会将连接返回给Engine的连接池,并且不会关闭连接。

engine.dispose() 将关闭连接池的所有连接。

如果设置,引擎将不使用连接池poolclass=NullPool。因此,连接(SQLAlchemy会话)将在之后直接关闭session.close()


4
.dispose等待所有未决的提交吗?
matanster

4
@matanster否,根据docs:“在处理引擎或回收垃圾时不会丢弃已检出的连接”。因此,任何未关闭会话将被有效忽略engine.dispose()
杰米·斯科特

0

LogicBank中,我进行了一系列的单元测试测试。每个测试在运行之前都会复制一个sqlite数据库,如下所示:

copyfile(src=nw_source, dst=nw_loc)

每个测试单独运行,但是在discover模式下失败。很明显,数据库副本没有发生。

看来,单元测试可能不是连续运行的。并非如此-单元测试实际上是串行运行的。这样就不是问题了(记录下来,也许可以节省一些时间)。

经过大量的重击后,看来这是因为该数据库未从先前的测试中完全关闭。 某种程度上干扰了上面的副本。我不知道为什么...

由于上面的帖子,我这样解决了它:

def tearDown(file: str, started_at: str, engine: sqlalchemy.engine.base.Engine, session: sqlalchemy.orm.session.Session):
"""
close session & engine, banner

:param file: caller, usually __file__
:param started_at: eg, str(datetime.now())
:param engine: eg, nw.logic import session, engine
:param session: from nw.logic import session, engine
:return:
"""

session.close()
engine.dispose(). # NOTE: close required before dispose!

print("\n")
print("**********************")
print("** Test complete, SQLAlchemy session/engine closed for: " + file)
print("** Started: " + started_at + " Ended: " + str(datetime.now()))
print("**********************")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.