如何关闭SQLAlchemy会话?

时间:2014-02-12 20:31:49

标签: python session sqlalchemy

按照我们在How to close sqlalchemy connection in MySQL中评论的内容,我正在检查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()不足够吗?

3 个答案:

答案 0 :(得分:62)

这里有一个关于“会话”这个词的中心混淆。我不确定这里,但看起来你可能会混淆SQLAlchemy SessionMySQL @@session,它指的是你第一次建立MySQL连接和断开连接时的范围。

这两个概念不一样。在特定的数据库连接上,SQLAlchemy会话通常表示一个或多个事务的范围。

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

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

这基本上意味着您希望禁用connection pooling。正如其他答案所提到的那样,很简单,use NullPool

答案 1 :(得分:40)

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

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

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

答案 2 :(得分: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("**********************")