我只是不知道如何使用aiosqlite模块,以便保持连接以备后用。
的示例async with aiosqlite.connect('file.db') as conn:
cursor = await conn.execute("SELECT 42;")
rows = await cursor.fetchall()
print('rows %s' % rows)
工作正常,但我想保持连接状态,以便可以在整个程序中使用它。
通常,使用sqlite,我打开一个连接,松开它,然后在程序的整个生命周期中使用它。
我也尝试过类似的事情:
conn = aiosqlite.connect('file.db')
c = await conn.__enter__()
AttributeError: 'Connection' object has no attribute '__enter__'
有没有上下文管理器可以使用此模块的方法吗?
答案 0 :(得分:1)
“最佳”方法是让应用程序的入口点使用上下文管理器方法创建aiosqlite连接,将对连接对象的引用存储在某个地方,然后从内部运行应用程序的“运行循环”方法那个背景。这将确保在您的应用程序退出时,适当清理sqlite连接。看起来可能像这样:
async def main():
async with aiosqlite.connect(...) as conn:
# save conn somewhere
await run_loop()
或者,您可以等待适当的进入/退出方法:
try:
conn = aiosqlite.connect(...)
await conn.__aenter__()
# do stuff
finally:
await conn.__aexit__()
无论如何,请注意aiosqlite的异步特性的确意味着共享连接可能会导致事务重叠。如果您需要确保并发查询是通过单独的事务进行的,那么每个事务将需要一个单独的连接。
根据Python sqlite docs关于共享连接的说明:
当使用具有相同连接的多个线程时,用户应序列化写入操作,以避免数据损坏。
这同样适用于aiosqlite和asyncio。例如,以下代码可能会将两个插入都重叠在一个事务中:
async def one(db):
await db.execute("insert ...")
await db.commit()
async def two(db):
await db.execute("insert ...")
await db.commit()
async def main():
async with aiosqlite.connect(...) as db:
await asyncio.gather(one(db), two(db))
正确的解决方案是为每个事务创建连接,或使用类似executescript
的方式一次执行整个事务。