Skip to main content

Короутины (coroutine)

Вопросы, касающиеся короутин (coroutine) и asyncio, относятся к этому разделу.

Примечание

Это содержание было взято непосредственно из документации и унаследованно от discord.py . Скорее всего, в будущем оно будет переписано.

Что такое coroutine?

Сoroutine это функция, которая должна быть вызвана с помощью await или yield from. Когда Python сталкивается с await, он останавливает выполнение функции в этот момент и работает над другими вещами, пока не вернется к этой точке и не завершит свою работу. Это позволяет вашей программе выполнять несколько задач одновременно без использования потоков или сложной многопроцессорной обработки.

Где я могу использовать await?

Вы можете использовать await только в async def функциях и нигде больше.

Что означает "blocking"?

В асинхронном программировании блокирующий вызов - это, по сути, все части функции, которые не являются await. Однако не отчаивайтесь, потому что не все формы блокировки плохи! Использование блокирующих вызовов неизбежно, но вы должны работать над тем, чтобы убедиться, что вы не чрезмерно блокируете функции. Помните, что если вы блокируете слишком долго, то ваш бот зависнет, так как в этот момент он не остановил выполнение функции для выполнения других действий.

Если ведение журнала включено, эта библиотека попытается предупредить вас о том, что происходит блокировка, с сообщением: Heartbeat blocked for more than N seconds. См. Раздел Настройка Ведения Журнала для получения подробной информации о включении ведения журнала.

Распространенным источником слишком длительной блокировки является что-то вроде time.sleep. Не делай этого. Используйте asyncio.sleep вместо этого. Аналогично этому примеру:

# Плохо
time.sleep(10)

# Хорошо
await asyncio.sleep(10)

Другим распространенным источником слишком длительной блокировки является использование HTTP-запросов с известным модулем Requests: HTTP for Humans™. В то время как Requests: HTTP for Humans™ - это удивительный модуль для неасинхронного программирования, он не является хорошим выбором для asyncio, потому что некоторые запросы могут блокировать цикл событий слишком долго. Вместо этого используйте библиотеку aiohttp, которая уже установлена с disnake.

Рассмотрим следующий пример:

# Плохо
r = requests.get("http://aws.random.cat/meow")
if r.status_code == 200:
json = r.json()
await channel.send(json["file"])

# Хорошо
async with aiohttp.ClientSession() as session:
async with session.get("http://aws.random.cat/meow") as r:
if r.status == 200:
json = await r.json()
await channel.send(json["file"])