#python #python-asyncio
Вопрос:
В этом минимальном примере я ожидаю, что программа будет печатать foo
и fuu
по мере выполнения задач.
import asyncio
async def coroutine():
while True:
print("foo")
async def main():
asyncio.create_task(coroutine())
#asyncio.run_coroutine_threadsafe(coroutine(),asyncio.get_running_loop())
while True:
print("fuu")
asyncio.run(main())
Программа будет только писать fuu
.
Моя цель состоит в том, чтобы просто две задачи выполнялись одновременно, но, похоже, созданная задача никогда не планируется.
Я также безуспешно пытался использовать run_coroutine_threadsafe
.
Если я добавлю await asyncio.sleep(1)
к основному. Созданная задача требует выполнения, и программа будет только писать foo
.
Что я должен сделать, чтобы выполнить две задачи одновременно с помощью asyncio ?
Комментарии:
1. Asyncio основан на совместной многозадачности, и
coroutine
ниmain
один из них не сотрудничает. Чтобы переключать задачи, вам нужноawait
выражение, которое ожидает чего-то, что приостанавливается в цикле событий. В игрушечных примерах это может быть что-то вродеawait asyncio.sleep(0.01)
; в реальном коде это что-то вродеline = await stream.readline()
,await websocket.send(msg)
, илиtodo = await queue.get()
.
Ответ №1:
Мне нравится этот вопрос, и объяснение этого вопроса рассказывает, как работают asyncio и python.
Спойлеры — Он работает аналогично однопоточной среде выполнения Javascript.
Итак, давайте посмотрим на ваш код. У вас работает только один основной поток, который будет работать непрерывно, так как планировщику python не нужно переключаться между потоками. Теперь дело в том, что ваш основной поток, создающий задачу, фактически создает сопрограмму(зеленые потоки, управляемые планировщиком python, а не планировщиком ОС), для выполнения которой требуется основной поток.
Теперь основной поток никогда не бывает свободным, так как вы поставили значение while True, он никогда не может свободно выполнять что-либо еще, и ваша задача никогда не выполняется, потому что планировщик python никогда не переключается, потому что он занят выполнением истинного кода.
В тот момент, когда вы переводите в спящий режим, он обнаруживает, что текущая задача находится в спящем режиме, и выполняет переключение контекста, и включается ваша сопрограмма.
Мое предложение. если ваши задачи тяжелы для ввода-вывода, используйте задачи/сопрограммы, и если они тяжелы для процессора, что в вашем случае ( while True
), создайте потоки или процессы Python, а затем планировщик ОС позаботится о выполнении ваших задач, они получат фрагмент процессора для запуска while True
.