Лучший способ открыть / закрыть соединение с БД с помощью async / await - PullRequest
0 голосов
/ 02 июня 2018

В учебных пособиях, которые я нашел, всегда открываются и закрываются соединения для каждого запроса, например:

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 является классом, что приводит к большому количеству классов / методов.

У меня есть привычка открывать соединение блокирующим образом, а затем использоватьОболочка для выполнения асинхронных вызовов БД и закрытия соединения только для того, чтобы корректно завершить работу сервера, что является лучшим методом в этом случае с async/await?

1 Ответ

0 голосов
/ 02 июня 2018

Не используя asyncpg, я предполагаю, что, как и в большинстве пакетов, совместимых с asyncio, существует менеджер контекста async, позволяющий выполнять именно то, что вы запрашиваете.

Что-то вроде:

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()

Я не уверен, насколько это хорошее объяснение, возможно, вам следует прочитать менеджеров контекста .

...