我从SQLite数据库执行select()
,然后执行insert()
:
engine = create_engine('sqlite:///testdb.db')
metadata = MetaData(bind=engine)
test = Table('test', metadata, autoload=True)
# Select all from pending_data
sel = select([test])
res = engine.execute(sel)
print res
# do an insert into pending_data
test.insert()\
.values(info='blah')\
.execute()
当我的代码执行INSERT行时,我收到以下错误:
sqlalchemy.exc.ResourceClosedError: This Connection is closed
但是,如果我将RES转换为如下所示的列表:
res = list(engine.execute(sel))
我的代码运行得很好。这里发生了什么事?
2条答案
按热度按时间lh80um4z1#
SQLAlChemy有两个必须了解的概念:连接和引擎。一个引擎可以支持多个同时连接。在您的示例中,您将表绑定到一个引擎。现在,每当您调用
.execute
时,都会为您执行的每个查询创建一个新连接。但是,Sqlite3只允许1个并发的“连接”。解决此问题的最佳方法是创建连接并显式使用它,而不是引擎自动创建的连接;并将该连接与
with
语句一起使用,这可确保连接在块的末尾关闭:为了理解这种行为,出现错误的原因是您在隐式创建和持有的集合中持有活动游标(这由
res
变量引用;在您使用它、关闭它或删除对它的引用之前,游标将处于活动状态,因此连接将处于活动状态,并且数据库将被锁定)。当您执行
list(res)
时,您正在消耗游标,并且它被SQLAlChemy关闭;如果结果的引用计数降到0,也会发生同样的情况。你也可以尝试以下方法来理解这一点,它们会像你预期的那样工作:
或
因此,始终完全使用ResultProxy或显式关闭它,或在完成后删除对它的引用。
如果您重用相同的连接,这不是问题;只有当您创建到SQLITE3数据库的新连接时(PostgreSQL、MySQL、Oracle等也可以很好地处理这一点)。
bybem2ql2#
对于我来说,当我尝试发布表的条目时,我收到了这个错误,我使用的是
sqlachmey
的新语法,我在使用select
时忘记了添加表类名称,所以我写成了select().where...
而不是select(tbaleNameClass).where...
,所以我得到了这个ResourceClosedError
。所以我唯一要做的就是正确地写出语法,而不是写成
写
Assessment
是表类名称因此,如果你们中的任何人首先得到相同的错误检查,那么您写的东西是正确的:)。