Корутины и задачи¶
В этом разделе описываются высокоуровневые API asyncio для работы с coroutines и Tasks.
Корутины¶
Coroutines, объявленные с синтаксисом async/await, являются предпочтительным способом написания приложений asyncio. Например, следующий фрагмент кода печатает «hello», ждет 1 секунду, а затем печатает «world»:
>>> import asyncio
>>> async def main():
... print('hello')
... await asyncio.sleep(1)
... print('world')
>>> asyncio.run(main())
hello
world
Обратите внимание, что простой вызов coroutine не приведет к планированию ее выполнения:
>>> main()
<coroutine object main at 0x1053bb7c8>
Чтобы фактически запустить coroutine, asyncio предоставляет три основных механизма:
Функция
asyncio.run()
для запуска функции верхнего уровня «main()» (см. пример выше).Ожидание в корутине. Следующий фрагмент кода выведет «hello» после ожидания в течение 1 секунды, а затем выведет «world» после ожидания в течение еще 2 секунд:
import asyncio import time async def say_after(delay, what): await asyncio.sleep(delay) print(what) async def main(): print(f"started at {time.strftime('%X')}") await say_after(1, 'hello') await say_after(2, 'world') print(f"finished at {time.strftime('%X')}") asyncio.run(main())
Ожидаемый результат:
started at 17:13:52 hello world finished at 17:13:55
Функция
asyncio.create_task()
для одновременного запуска coroutines как asyncioTasks
.Давайте изменим приведенный выше пример и запустим две ``say_after``корутины одновременно:
async def main(): task1 = asyncio.create_task( say_after(1, 'hello')) task2 = asyncio.create_task( say_after(2, 'world')) print(f"started at {time.strftime('%X')}") # Wait until both tasks are completed (should take # around 2 seconds.) await task1 await task2 print(f"finished at {time.strftime('%X')}")
Обратите внимание, что ожидаемый результат теперь показывает, что фрагмент выполняется на 1 секунду быстрее, чем раньше:
started at 17:14:32 hello world finished at 17:14:34
Ожидания¶
Мы говорим, что объект является awaitable, если он может быть использован в выражении await
. Многие API asyncio разработаны так, чтобы принимать awaitables.
Существует три основных типа ожидаемых объектов: корутины, задачи и фьючерсы.
Корутины
Корутины Python являются awaitables и поэтому могут быть ожидаемы от других корутин:
import asyncio
async def nested():
return 42
async def main():
# Nothing happens if we just call "nested()".
# A coroutine object is created but not awaited,
# so it *won't run at all*.
nested()
# Let's do it differently now and await it:
print(await nested()) # will print "42".
asyncio.run(main())
Важно
В данной документации термин «coroutine» может использоваться для двух тесно связанных понятий:
кораутинная функция: функция
async def
;объект корутинной функции: объект, возвращаемый при вызове корутинной функции.
asyncio также поддерживает унаследованные generator-based coroutines.
Задачи
Задачи Tasks используются для планирования короутинов concurrently.
Когда coroutine обернута в Task с функциями типа asyncio.create_task()
, coroutine автоматически планируется к выполнению в ближайшее время:
import asyncio
async def nested():
return 42
async def main():
# Schedule nested() to run soon concurrently
# with "main()".
task = asyncio.create_task(nested())
# "task" can now be used to cancel "nested()", or
# can simply be awaited to wait until it is complete:
await task
asyncio.run(main())
Фьючерсы
Future
- это специальный низкоуровневый ожидаемый объект, который представляет собой эвентуальный результат асинхронной операции.
Когда объект Future ожидается, это означает, что coroutine будет ждать, пока Future не будет разрешен в каком-то другом месте.
Объекты будущего в asyncio необходимы для того, чтобы код на основе обратного вызова можно было использовать с async/await.
Обычно нет необходимости создавать объекты Future в коде на уровне приложения.
Будущие объекты, иногда открываемые библиотеками и некоторыми API asyncio, можно ожидать:
async def main():
await function_that_returns_a_future_object()
# this is also valid:
await asyncio.gather(
function_that_returns_a_future_object(),
some_python_coroutine()
)
Хорошим примером низкоуровневой функции, возвращающей объект Future, является loop.run_in_executor()
.
Запуск программы asyncio¶
-
asyncio.
run
(coro, *, debug=False)¶ Выполните coroutine coro и верните результат.
Эта функция запускает переданную корутину, заботясь об управлении циклом событий asyncio, финализации асинхронных генераторов и закрытии пула потоков.
Эта функция не может быть вызвана, когда в том же потоке выполняется другой цикл событий asyncio.
Если debug имеет значение
True
, цикл событий будет выполняться в режиме отладки.Эта функция всегда создает новый цикл событий и закрывает его в конце. Она должна использоваться как основная точка входа для программ asyncio, и в идеале должна вызываться только один раз.
Пример:
async def main(): await asyncio.sleep(1) print('hello') asyncio.run(main())
Добавлено в версии 3.7.
Изменено в версии 3.9: Обновлено для использования
loop.shutdown_default_executor()
.Примечание
Исходный код для
asyncio.run()
можно найти в Lib/asyncio/runners.py.
Создание задач¶
-
asyncio.
create_task
(coro, *, name=None)¶ Заверните coro coroutine в
Task
и запланируйте его выполнение. Верните объект Task.Если name не является
None
, оно устанавливается как имя задачи с помощьюTask.set_name()
.Задание выполняется в цикле, возвращенном командой
get_running_loop()
,RuntimeError
поднимается, если в текущем потоке нет запущенного цикла.Важно
Сохраните ссылку на результат этой функции, чтобы избежать исчезновения задачи в середине выполнения. В цикле событий сохраняются только слабые ссылки на задачи. Задача, на которую нет ссылки в другом месте, может быть собрана в мусор в любой момент, даже до того, как она будет выполнена. Для надежного выполнения фоновых задач по принципу «запустил и забыл», соберите их в коллекцию:
background_tasks = set() for i in range(10): task = asyncio.create_task(some_coro(param=i)) # Add task to the set. This creates a strong reference. background_tasks.add(task) # To prevent keeping references to finished tasks forever, # make each task remove its own reference from the set after # completion: task.add_done_callback(background_tasks.discard)
Добавлено в версии 3.7.
Изменено в версии 3.8: Добавлен параметр name.
Спать¶
-
coroutine
asyncio.
sleep
(delay, result=None)¶ Блокировать на задержку секунд.
Если указан result, он возвращается вызывающей стороне после завершения работы программы.
sleep()
всегда приостанавливает выполнение текущей задачи, позволяя выполнять другие задачи.Установка задержки в 0 обеспечивает оптимизированный путь для выполнения других задач. Это может быть использовано долго выполняющимися функциями, чтобы избежать блокировки цикла событий на весь период вызова функции.
Deprecated since version 3.8, removed in version 3.10: Параметр
loop
. Начиная с версии 3.7 эта функция неявно получает текущий запущенный цикл. Для получения дополнительной информации см. раздел What’s New in 3.10’s Removed section.Пример корутины, выводящей текущую дату каждую секунду в течение 5 секунд:
import asyncio import datetime async def display_date(): loop = asyncio.get_running_loop() end_time = loop.time() + 5.0 while True: print(datetime.datetime.now()) if (loop.time() + 1.0) >= end_time: break await asyncio.sleep(1) asyncio.run(display_date())
Изменено в версии 3.10: Удален параметр loop.
Одновременное выполнение задач¶
-
awaitable
asyncio.
gather
(*aws, return_exceptions=False)¶ Выполните awaitable objects в последовательности aws последовательно.
Если какой-либо awaitable в aws является coroutine, он автоматически планируется как Task.
Если все ожидания завершены успешно, результатом будет агрегированный список возвращаемых значений. Порядок значений результата соответствует порядку ожиданий в aws.
Если return_exceptions равно
False
(по умолчанию), то первое возникшее исключение немедленно передается задаче, ожидающей наgather()
. Другие ожидающие задачи в последовательности aws не будут отменены и продолжат выполнение.Если return_exceptions имеет значение
True
, исключения рассматриваются так же, как и успешные результаты, и объединяются в списке результатов.Если
gather()
отменено, все переданные ожидания (которые еще не завершились) также отменяются.Если какая-либо Задача или Будущее из последовательности aws отменяется, она рассматривается как если бы она вызвала
CancelledError
– вызовgather()
в этом случае не отменяется. Это делается для того, чтобы отмена одной представленной Задачи/Будущего не привела к отмене других Задач/Будущего.Изменено в версии 3.10: Удален параметр loop.
Пример:
import asyncio async def factorial(name, number): f = 1 for i in range(2, number + 1): print(f"Task {name}: Compute factorial({number}), currently i={i}...") await asyncio.sleep(1) f *= i print(f"Task {name}: factorial({number}) = {f}") return f async def main(): # Schedule three calls *concurrently*: L = await asyncio.gather( factorial("A", 2), factorial("B", 3), factorial("C", 4), ) print(L) asyncio.run(main()) # Expected output: # # Task A: Compute factorial(2), currently i=2... # Task B: Compute factorial(3), currently i=2... # Task C: Compute factorial(4), currently i=2... # Task A: factorial(2) = 2 # Task B: Compute factorial(3), currently i=3... # Task C: Compute factorial(4), currently i=3... # Task B: factorial(3) = 6 # Task C: Compute factorial(4), currently i=4... # Task C: factorial(4) = 24 # [2, 6, 24]
Примечание
Если return_exceptions равно False, отмена функции gather() после того, как она была помечена как выполненная, не отменит ни одного из переданных ожиданий. Например, gather может быть помечена как выполненная после распространения исключения на вызывающую сторону, поэтому вызов
gather.cancel()
после перехвата исключения (поднятого одним из ожиданий) из gather не приведет к отмене других ожиданий.Изменено в версии 3.7: Если отменяется сам gather, отмена распространяется независимо от return_exceptions.
Изменено в версии 3.10: Удален параметр loop.
Не рекомендуется, начиная с версии 3.10: Предупреждение об износе выдается, если не указаны позиционные аргументы или не все позиционные аргументы являются Future-like объектами и нет запущенного цикла событий.
Защита от отмены¶
-
awaitable
asyncio.
shield
(aw)¶ Защитить awaitable object от превращения в
cancelled
.Если aw является корутиной, то она автоматически запланирована как задача.
Заявление:
res = await shield(something())
эквивалентно:
res = await something()
за исключением того, что если содержащая его coroutine отменяется, то Task, выполняющийся в
something()
, не отменяется. С точки зренияsomething()
, отмена не произошла. Хотя ее вызывающая часть все равно отменяется, поэтому выражение «await» все равно вызывает ошибкуCancelledError
.Если
something()
отменяется другим способом (т.е. изнутри себя), это также отменяетshield()
.Если необходимо полностью игнорировать отмену (не рекомендуется), функция
shield()
должна быть объединена с предложением try/except, как показано ниже:try: res = await shield(something()) except CancelledError: res = None
Изменено в версии 3.10: Удален параметр loop.
Не рекомендуется, начиная с версии 3.10: Предупреждение об устаревании выдается, если aw не является Future-like объектом и нет запущенного цикла событий.
Тайм-ауты¶
-
coroutine
asyncio.
wait_for
(aw, timeout)¶ Дождитесь завершения aw awaitable с таймаутом.
Если aw является корутиной, то она автоматически запланирована как задача.
timeout может быть либо
None
, либо float или int - число секунд для ожидания. Если timeout равенNone
, блокируйте до тех пор, пока будущее не завершится.Если происходит тайм-аут, он отменяет задание и поднимает
asyncio.TimeoutError
.Чтобы избежать задачи
cancellation
, оберните ее вshield()
.Функция будет ждать, пока будущее не будет фактически отменено, поэтому общее время ожидания может превысить timeout. Если во время отмены произойдет исключение, оно будет передано.
Если ожидание отменяется, то будущее aw также отменяется.
Изменено в версии 3.10: Удален параметр loop.
Пример:
async def eternity(): # Sleep for one hour await asyncio.sleep(3600) print('yay!') async def main(): # Wait for at most 1 second try: await asyncio.wait_for(eternity(), timeout=1.0) except asyncio.TimeoutError: print('timeout!') asyncio.run(main()) # Expected output: # # timeout!
Изменено в версии 3.7: Когда aw отменяется из-за таймаута,
wait_for
ожидает отмены aw. Ранее он немедленно вызывалasyncio.TimeoutError
.Изменено в версии 3.10: Удален параметр loop.
Примитивы ожидания¶
-
coroutine
asyncio.
wait
(aws, *, timeout=None, return_when=ALL_COMPLETED)¶ Выполнять awaitable objects в итерабле aws параллельно и блокировать до выполнения условия, заданного return_when.
Итерабельность aws не должна быть пустой.
Возвращает два набора Задач/Функций:
(done, pending)
.Использование:
done, pending = await asyncio.wait(aws)
timeout (число float или int), если указано, может использоваться для управления максимальным количеством секунд ожидания перед возвратом.
Обратите внимание, что эта функция не поднимает
asyncio.TimeoutError
. Фьючерсы или задачи, которые не были выполнены в момент тайм-аута, просто возвращаются во втором наборе.return_when указывает, когда эта функция должна вернуться. Это должна быть одна из следующих констант:
Постоянная
Описание
FIRST_COMPLETED
Функция возвращается, когда любое будущее завершается или отменяется.
FIRST_EXCEPTION
Функция вернется, когда любое будущее завершится, вызвав исключение. Если ни одно будущее не вызывает исключения, то это эквивалентно
ALL_COMPLETED
.ALL_COMPLETED
Функция вернется, когда все фьючерсы завершатся или будут отменены.
В отличие от
wait_for()
,wait()
не отменяет фьючерсы при возникновении тайм-аута.Не рекомендуется, начиная с версии 3.8: Если какой-либо awaitable в aws является coroutine, он автоматически планируется как Task. Передача объектов coroutines в
wait()
напрямую неактуальна, так как приводит к confusing behavior.Изменено в версии 3.10: Удален параметр loop.
Примечание
wait()
автоматически планирует короутины как Задачи и позже возвращает эти неявно созданные объекты Задач в наборах(done, pending)
. Поэтому следующий код не будет работать так, как ожидалось:async def foo(): return 42 coro = foo() done, pending = await asyncio.wait({coro}) if coro in done: # This branch will never be run!
Вот как можно исправить приведенный выше фрагмент:
async def foo(): return 42 task = asyncio.create_task(foo()) done, pending = await asyncio.wait({task}) if task in done: # Everything will work as expected now.
Deprecated since version 3.8, will be removed in version 3.11: Передача объектов coroutine непосредственно в
wait()
устарела.Изменено в версии 3.10: Удален параметр loop.
-
asyncio.
as_completed
(aws, *, timeout=None)¶ Выполнять awaitable objects в итерабле aws одновременно. Возвращает итератор короутинов. Каждая возвращенная корутина может быть ожидаема для получения самого раннего следующего результата из итератора оставшихся ожидаемых.
Повышает
asyncio.TimeoutError
, если таймаут произойдет до того, как все фьючерсы будут выполнены.Изменено в версии 3.10: Удален параметр loop.
Пример:
for coro in as_completed(aws): earliest_result = await coro # ...
Изменено в версии 3.10: Удален параметр loop.
Не рекомендуется, начиная с версии 3.10: Предупреждение об износе выдается, если не все ожидаемые объекты в итерабле aws являются Future-подобными объектами и нет запущенного цикла событий.
Бег по нитям¶
-
coroutine
asyncio.
to_thread
(func, /, *args, **kwargs)¶ Асинхронное выполнение функции func в отдельном потоке.
Любые *args и **kwargs, переданные для этой функции, напрямую передаются в func. Также передается текущее значение
contextvars.Context
, что позволяет обращаться к контекстным переменным из потока цикла событий в отдельном потоке.Возвращает корутину, которую можно ожидать, чтобы получить конечный результат func.
Эта функция coroutine в первую очередь предназначена для выполнения функций/методов, связанных с IO, которые в противном случае блокировали бы цикл событий, если бы выполнялись в главном потоке. Например:
def blocking_io(): print(f"start blocking_io at {time.strftime('%X')}") # Note that time.sleep() can be replaced with any blocking # IO-bound operation, such as file operations. time.sleep(1) print(f"blocking_io complete at {time.strftime('%X')}") async def main(): print(f"started main at {time.strftime('%X')}") await asyncio.gather( asyncio.to_thread(blocking_io), asyncio.sleep(1)) print(f"finished main at {time.strftime('%X')}") asyncio.run(main()) # Expected output: # # started main at 19:50:53 # start blocking_io at 19:50:53 # blocking_io complete at 19:50:54 # finished main at 19:50:54
Прямой вызов blocking_io() в любой короутине заблокирует цикл событий на все его время, что приведет к дополнительной 1 секунде времени выполнения. Вместо этого, используя asyncio.to_thread(), мы можем запустить его в отдельном потоке без блокировки цикла событий.
Примечание
Из-за GIL, asyncio.to_thread() обычно можно использовать только для того, чтобы сделать IO-связанные функции неблокирующими. Однако, для модулей расширения, выпускающих GIL, или альтернативных реализаций Python, не имеющих его, asyncio.to_thread() может также использоваться для функций, связанных с процессором.
Добавлено в версии 3.9.
Планирование из других потоков¶
-
asyncio.
run_coroutine_threadsafe
(coro, loop)¶ Послать корутину в заданный цикл событий. Безопасно для потоков.
Возвращает
concurrent.futures.Future
для ожидания результата от другого потока ОС.Эта функция должна вызываться из потока ОС, отличного от того, в котором выполняется цикл событий. Пример:
# Create a coroutine coro = asyncio.sleep(1, result=3) # Submit the coroutine to a given loop future = asyncio.run_coroutine_threadsafe(coro, loop) # Wait for the result with an optional timeout argument assert future.result(timeout) == 3
Если в корутине возникает исключение, то возвращенное Future будет оповещено. Его также можно использовать для отмены задачи в цикле событий:
try: result = future.result(timeout) except concurrent.futures.TimeoutError: print('The coroutine took too long, cancelling the task...') future.cancel() except Exception as exc: print(f'The coroutine raised an exception: {exc!r}') else: print(f'The coroutine returned: {result!r}')
См. раздел concurrency and multithreading в документации.
В отличие от других функций asyncio, эта функция требует явной передачи аргумента loop.
Добавлено в версии 3.5.1.
Интроспекция¶
-
asyncio.
current_task
(loop=None)¶ Возвращает текущий запущенный экземпляр
Task
илиNone
, если ни одна задача не запущена.Если loop равен
None
, тоget_running_loop()
используется для получения текущего цикла.Добавлено в версии 3.7.
-
asyncio.
all_tasks
(loop=None)¶ Возвращает набор еще не завершенных
Task
объектов, выполняемых циклом.Если loop равен
None
, то для получения текущего цикла используетсяget_running_loop()
.Добавлено в версии 3.7.
Объект задачи¶
-
class
asyncio.
Task
(coro, *, loop=None, name=None)¶ Объект
Future-like
, который запускает Python coroutine. Не является потокобезопасным.Задачи используются для запуска программ в циклах событий. Если основная программа ожидает будущего, задача приостанавливает выполнение основной программы и ожидает завершения будущего. Когда будущее закончено, выполнение обернутой программы возобновляется.
Циклы событий используют кооперативное планирование: цикл событий запускает одну Задачу за раз. Пока задача ожидает завершения Future, цикл событий запускает другие задачи, обратные вызовы или выполняет операции ввода-вывода.
Для создания Задач используйте функцию высокого уровня
asyncio.create_task()
или функции низкого уровняloop.create_task()
илиensure_future()
. Не рекомендуется создавать Задачи вручную.Для отмены запущенной задачи используйте метод
cancel()
. Его вызов приведет к тому, что Task выбросит исключениеCancelledError
в обернутую coroutine. Если во время отмены корутина ожидает объект Future, объект Future будет отменен.cancelled()
может быть использован для проверки того, была ли отменена задача. Метод возвращаетTrue
, если обернутая короутина не подавила исключениеCancelledError
и действительно была отменена.asyncio.Task
наследует отFuture
все свои API, кромеFuture.set_result()
иFuture.set_exception()
.Задачи поддерживают модуль
contextvars
. Когда создается задача, она копирует текущий контекст, а затем запускает свою программу в скопированном контексте.Изменено в версии 3.7: Добавлена поддержка модуля
contextvars
.Изменено в версии 3.8: Добавлен параметр name.
Не рекомендуется, начиная с версии 3.10: Предупреждение об устаревании выдается, если не указан loop и нет запущенного цикла событий.
-
cancel
(msg=None)¶ Запрос на отмену задания.
Это позволяет организовать исключение
CancelledError
, которое будет брошено в обернутую coroutine на следующем цикле цикла событий.Затем корутина имеет возможность очистить или даже отклонить запрос, подавив исключение с помощью команды
try
… … ….except CancelledError
…finally
блоком. Поэтому, в отличие отFuture.cancel()
,Task.cancel()
не гарантирует, что задача будет отменена, хотя полное подавление отмены не является обычным явлением и активно не рекомендуется.Изменено в версии 3.9: Добавлен параметр msg.
Следующий пример иллюстрирует, как корутины могут перехватывать запрос на отмену:
async def cancel_me(): print('cancel_me(): before sleep') try: # Wait for 1 hour await asyncio.sleep(3600) except asyncio.CancelledError: print('cancel_me(): cancel sleep') raise finally: print('cancel_me(): after sleep') async def main(): # Create a "cancel_me" Task task = asyncio.create_task(cancel_me()) # Wait for 1 second await asyncio.sleep(1) task.cancel() try: await task except asyncio.CancelledError: print("main(): cancel_me is cancelled now") asyncio.run(main()) # Expected output: # # cancel_me(): before sleep # cancel_me(): cancel sleep # cancel_me(): after sleep # main(): cancel_me is cancelled now
-
cancelled
()¶ Возвращает
True
, если задача отменена.Задача отменена, если отмена была запрошена с помощью
cancel()
и обернутая coroutine распространила брошенное в нее исключениеCancelledError
.
-
done
()¶ Возвращает
True
, если задача выполнена.Задача закончена, когда обернутая coroutine либо вернула значение, либо вызвала исключение, либо задача была отменена.
-
result
()¶ Возвращает результат выполнения задачи.
Если задача выполнена, возвращается результат обернутой программы (или, если программа вызвала исключение, это исключение вызывается повторно).
Если задача была отменена, этот метод вызывает исключение
CancelledError
.Если результат задачи еще не доступен, этот метод вызывает исключение
InvalidStateError
.
-
exception
()¶ Возвращает исключение из задачи.
Если обернутая программа вызвала исключение, то это исключение возвращается. Если обернутая программа вернулась нормально, этот метод возвращает
None
.Если задача была отменена, этот метод вызывает исключение
CancelledError
.Если задача еще не закончена, этот метод вызывает исключение
InvalidStateError
.
-
add_done_callback
(callback, *, context=None)¶ Добавьте обратный вызов, который будет выполняться, когда задача будет выполнена.
Этот метод следует использовать только в низкоуровневом коде, основанном на обратном вызове.
Более подробную информацию см. в документации по
Future.add_done_callback()
.
-
remove_done_callback
(callback)¶ Удалить callback из списка обратных вызовов.
Этот метод следует использовать только в низкоуровневом коде, основанном на обратном вызове.
Более подробную информацию см. в документации по
Future.remove_done_callback()
.
-
get_stack
(*, limit=None)¶ Возвращает список кадров стека для этой задачи.
Если обернутая программа не завершена, возвращается стек, в котором она приостановлена. Если программа завершилась успешно или была отменена, возвращается пустой список. Если программа завершилась в результате исключения, возвращается список кадров трассировки.
Кадры всегда располагаются в порядке от самого старого к самому новому.
Для приостановленной coroutine возвращается только один кадр стека.
Необязательный аргумент limit задает максимальное количество возвращаемых кадров; по умолчанию возвращаются все доступные кадры. Порядок возвращаемого списка отличается в зависимости от того, возвращается ли стек или трассировка: возвращаются самые новые кадры стека, но возвращаются самые старые кадры трассировки. (Это соответствует поведению модуля traceback).
-
print_stack
(*, limit=None, file=None)¶ Выведите стек или обратную трассировку для этой задачи.
Это дает вывод, аналогичный выводу модуля traceback для кадров, полученных с помощью
get_stack()
.Аргумент limit передается в
get_stack()
напрямую.Аргумент file - это поток ввода/вывода, в который записывается вывод; по умолчанию вывод записывается в
sys.stderr
.
-
get_name
()¶ Возвращает имя задачи.
Если имя не было явно присвоено задаче, реализация asyncio Task по умолчанию генерирует имя по умолчанию во время инстанцирования.
Добавлено в версии 3.8.
-
Корутины на основе генераторов¶
Примечание
Поддержка coroutines на основе генераторов является устаревшей и будет удалена в Python 3.11.
Корутины на основе генераторов появились раньше, чем синтаксис async/await. Они представляют собой генераторы Python, которые используют выражения yield from
для ожидания на Futures и других coroutines.
Корутины на основе генераторов должны быть украшены @asyncio.coroutine
, хотя это не является обязательным условием.
-
@
asyncio.
coroutine
¶ Декоратор для маркировки coroutines на основе генератора.
Этот декоратор позволяет устаревшим генераторным корутинам быть совместимыми с кодом async/await:
@asyncio.coroutine def old_style_coroutine(): yield from asyncio.sleep(1) async def main(): await old_style_coroutine()
Этот декоратор не следует использовать для :keyword:`async def`корутинов.
Deprecated since version 3.8, will be removed in version 3.11: Вместо этого используйте
async def
.
-
asyncio.
iscoroutine
(obj)¶ Возвращает
True
, если obj является coroutine object.Этот метод отличается от
inspect.iscoroutine()
тем, что он возвращаетTrue
для coroutines на основе генератора.
-
asyncio.
iscoroutinefunction
(func)¶ Возвращает
True
, если func является coroutine function.Этот метод отличается от
inspect.iscoroutinefunction()
тем, что он возвращаетTrue
для генераторных функций coroutine, украшенных@coroutine
.