#python #async-await #task #python-asyncio #coroutine
Вопрос:
асинсио,подожди, говорит:
Передача объектов сопрограмм напрямую в wait() не рекомендуется, так как это приводит к запутанному поведению.
и выдает это за сбивающее с толку поведение:
wait()
автоматически планирует сопрограммы как задачи, а затем возвращает эти неявно созданные объекты задач в наборах (готово, ожидание). Поэтому следующий код не будет работать должным образом: [Я изменил приведенный ниже фрагмент кода, чтобы он работал]async def foo(): return 42 async def main(): coro = foo() done, pending = await asyncio.wait({coro}) if coro in done: # This branch will never be run! print('yay!') asyncio.run(main())
Я только начал узнавать об asyncio
этом , поэтому не совсем понимаю. Может кто-нибудь объяснить?
Комментарии:
1.
asyncio.wait
не обязательно вызывается вawait
заявлении, и это не является частью путаницы, которая здесь подразумевается.
Ответ №1:
Пример кода, приведенный в документации, является:
coro = foo()
done, pending = await asyncio.wait({coro})
if coro in done:
# This branch will never be run!
Причина, по которой этот код дает неожиданные результаты, заключается в следующем:
coro
является объектом сопрограммы.- Когда он передается
asyncio.wait
, он автоматически создаетTask
из него объект (который отличается от объекта сопрограммы), напримерcoro_task = create_task(coro)
(см.create_task
). - Когда
asyncio.wait
это будет сделано, он вернет два набора:- набор задач, которые уже выполнены
- набор задач, которые еще не выполнены
Таким образом, в этом случае он вернет один набор, который содержит coro_task
, и один набор, который пуст.
Обратите внимание, что исходный объект сопрограммы coro
(который отличается от coro_task
) не содержится ни в одном из наборов, поэтому проверять, находится ли он в наборе «готово», бессмысленно — он никогда не будет содержаться, даже если соответствующая задача coro_task
уже выполнена.
Исправление заключается в создании Task
объекта для coro
внешнего asyncio.wait
, что позволит проверить, содержится ли тот же объект в одном или другом из возвращаемых наборов, чтобы определить, выполнена ли задача.
В версиях Python , начиная с 3.8, вы получите предупреждение об устаревании, если передадите сопрограмму asyncio.wait
, и начиная с версии 3.11 это будет ошибка, т. е. вы вынуждены использовать «исправленный» код.