Python的 records 库使用起来特别方便,对 RedShift, Postgres, MySQL, SQLite, Oracle, 和 MS-SQL 都提供支持。但最近在测试 records 操作 sqlite 数据库的时候,却出现一个莫名的错误。代码只有 4 行,是这样的:
import records
db = records.Database('sqlite:///testdb.db')
rows = db.query('select * from users')
print (rows.dataset)
运行报如下错误:
sqlalchemy.exc.ProgrammingError: (sqlite3.ProgrammingError) Cannot operate on a closed database.
按理说 records 自动管理数据库的连接,自动管理数据连接的打开和关闭,为什么会出现数据库关闭呢。跟踪了一下代码,发现原因是这样的。
records 库的 Database
对象在 __init__()
方法中调用 sqlalchemy 库的 create_engine()
方法,并且将 open
属性设为 True。
然后 Database
的 query()
方法中,先调用 Database.get_connection()
方法,返回一个 Connection
对象,再执行 Connection
对象的 query()
方法。
但是 Connection 类有一个 __exit__()
方法,我们知道,Python 的 __enter__()
方法和 __exit__()
方法是实现上下文管理的,所以有 with 语句,Connection 对象执行完 query()
方法后,会自动调用 __exit__()
方法,将 connection 关闭了。这个就是错误的原因。
知道原因,解决办法也就简单了,直接调用 Connection 对象的 query()
方法,将代码修改如下:
import records
db = records.Database('sqlite:///testdb.db')
conn = db.get_connection()
rows = conn.query('select * from users')
print (rows.dataset)
网友评论