退出WITH语句后Python不会自动关闭与sqlite3的连接?

问题描述 投票:0回答:2

这是一段在Python 3.10.5上运行的代码-

with sqlite3.connect("test.db") as db:
    cursor = db.cursor()
    cursor.execute("""CREATE TABLE IF NOT EXISTS testtable(id integer PRIMARY KEY, name text);""")
    cursor.execute("""INSERT INTO testtable(id, name) VALUES (1, "XYZ")""")
    db.commit()
        

cursor.execute("select * from testtable")
for x in cursor.fetchall():
    print(x)

现在,根据我对WITH语句工作方式的理解,与数据库的连接将在代码块末尾自动关闭,而不需要我显式调用

db.close()
,类似于文件I/O操作的处理方式。这意味着下一个
cursor.execute()
失败,因为它位于语句之外,因此无效。

但是,它仍然运行!我能够看到表的内容。这里发生了什么?

python python-3.x sqlite with-statement database-cursor
2个回答
1
投票

文件的上下文管理 (

with file(...) as x
) 会在退出块时自动关闭文件。然而,一般来说,开发人员可以自由地使用上下文来管理他们想要的任何操作。

sqlite3
的情况下,在
with
块中使用数据库连接对象会创建 数据库事务。这很有用,因为当
with
块正常退出时,事务会自动提交,或者如果出现异常,事务会自动回滚。连接本身不会在块结束时自动关闭。请参阅 sqlite3 文档 和相关的 过去的 StackOverflow 线程

如果您希望连接自动关闭,请参阅glglgl的这个答案


0
投票

sqlite3.connect
不能用作自关闭上下文管理器(如文件)。

可以使用生成的连接对象作为上下文管理器;请参阅 Python sqlite3 文档的这一部分,但要了解事务。

该文档还有此注释:

上下文管理器既不会隐式打开新事务,也不会关闭连接。如果您需要关闭上下文管理器,请考虑使用 contextlib.looking()。

所以尝试一下

import sqlite3
import contextlib

with contextlib.closing(sqlite3.connect("test.db")) as db:
    cursor = db.cursor()
    cursor.execute("""CREATE TABLE IF NOT EXISTS testtable(id integer PRIMARY KEY, name text);""")
    cursor.execute("""INSERT INTO testtable(id, name) VALUES (1, "XYZ")""")
    db.commit()


cursor.execute("select * from testtable")
for x in cursor.fetchall():
    print(x)

这引发了这个异常:

Traceback (most recent call last):
  File "/Users/evert/scratch/sqlitewith.py", line 12, in <module>
    cursor.execute("select * from testtable")
sqlite3.ProgrammingError: Cannot operate on a closed database.
© www.soinside.com 2019 - 2024. All rights reserved.