open/close 与 async/await 数据库连接的最佳方式
Best way to open/close DB Connection with async/await
在我找到的教程中,总是为每个请求打开和关闭连接,例如:
import asyncio
import asyncpg
async def run():
conn = await asyncpg.connect(user='user', password='password',
database='database', host='127.0.0.1')
values = await conn.fetch('''SELECT * FROM mytable''')
await conn.close()
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
虽然这适用于一个单一的功能,但网络应用程序呢?
IE:例如在 Tornado 中,每个 URL 都是一个 class,这导致很多 classes/methods.
我习惯以阻塞方式打开连接,然后使用包装器进行异步数据库调用,关闭连接只是为了正常关闭服务器,在这种情况下最好的做法是async/await
?
在没有使用 asyncpg 的情况下,我假设像在大多数 asyncio 兼容包中一样,有一个异步上下文管理器可以满足您的要求。
类似于:
async with asyncpg.create_pool(**kwargs) as pool:
async with pool.acquire() as connection:
async with connection.transaction():
result = await connection.fetchval(fetch stuff)
connection.execute(insert stuff with result)
(取自)
检查文档中提到的上下文管理器或带有 async with
语句的示例,或者如果没有其他内容,则检查源代码中的 类 实现了 __aenter__
、__aexit__
方法。
编辑 1:
上面的示例部分取自我链接到的问题,部分是为了完整性而设计的。但是要解决您对 with 语句的作用的评论:
async with asyncpg.create_pool(**kwargs) as pool:
#in this block pool is created and open
async with pool.acquire() as connection:
# in this block connection is acquired and open
async with connection.transaction():
# in this block each executed statement is in a transaction
execute_stuff_with_connection(connection)
# now we are back up one logical block so the transaction is closed
do_stuff_without_transaction_but_with_connection(connection)
# now we are up another block and the connection is closed and returned to the pool
do_more_stuff_with_pool(pool)
# now we are up another level and the pool is closed/exited/cleaned up
done_doing_async_stuff()
我不确定这个解释有多好,也许你应该继续阅读 context managers。
在我找到的教程中,总是为每个请求打开和关闭连接,例如:
import asyncio
import asyncpg
async def run():
conn = await asyncpg.connect(user='user', password='password',
database='database', host='127.0.0.1')
values = await conn.fetch('''SELECT * FROM mytable''')
await conn.close()
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
虽然这适用于一个单一的功能,但网络应用程序呢?
IE:例如在 Tornado 中,每个 URL 都是一个 class,这导致很多 classes/methods.
我习惯以阻塞方式打开连接,然后使用包装器进行异步数据库调用,关闭连接只是为了正常关闭服务器,在这种情况下最好的做法是async/await
?
在没有使用 asyncpg 的情况下,我假设像在大多数 asyncio 兼容包中一样,有一个异步上下文管理器可以满足您的要求。
类似于:
async with asyncpg.create_pool(**kwargs) as pool:
async with pool.acquire() as connection:
async with connection.transaction():
result = await connection.fetchval(fetch stuff)
connection.execute(insert stuff with result)
(取自
检查文档中提到的上下文管理器或带有 async with
语句的示例,或者如果没有其他内容,则检查源代码中的 类 实现了 __aenter__
、__aexit__
方法。
编辑 1:
上面的示例部分取自我链接到的问题,部分是为了完整性而设计的。但是要解决您对 with 语句的作用的评论:
async with asyncpg.create_pool(**kwargs) as pool:
#in this block pool is created and open
async with pool.acquire() as connection:
# in this block connection is acquired and open
async with connection.transaction():
# in this block each executed statement is in a transaction
execute_stuff_with_connection(connection)
# now we are back up one logical block so the transaction is closed
do_stuff_without_transaction_but_with_connection(connection)
# now we are up another block and the connection is closed and returned to the pool
do_more_stuff_with_pool(pool)
# now we are up another level and the pool is closed/exited/cleaned up
done_doing_async_stuff()
我不确定这个解释有多好,也许你应该继续阅读 context managers。