Почему loop.run_forever() блокирует мой основной поток?
Во время обучения asyncio я пробовал этот код:
import asyncio
from asyncio.coroutines import coroutine
@coroutine
def coro():
counter: int = 0
while True:
print("Executed" + str(counter))
counter += 1
yield
loop = asyncio.get_event_loop()
loop.run_until_complete(coro())
loop.run_forever()
print("Finished!")
Я ожидал, что сопрограмма будет выполнена только один раз, потому что она содержит выход и должна была вернуть управление вызывающей стороне. Результат, который я ожидал, был:
Executed 0
Finished!
Я ожидал такого поведения, потому что думал, что цикл будет запускать сопрограмму навсегда, как только каждый "кадр" будет возвращаться вызывающей программе после каждого выполнения (что-то вроде фонового потока, но совместным образом). Но вместо этого он запускает сопрограмму навсегда, не возвращаясь? Вывод следующий:
Executed 0
Executed 1
Executed 2
Executed 3
...
Кто-нибудь может объяснить, почему это происходит вместо моих ожиданий?
Приветствия.
1 ответ
У вас есть пара проблем. Когда вы звоните run_until_complete
, это ждет coro
закончить, прежде чем перейти к вашему run_forever
вызов. Как вы определили, coro
никогда не заканчивается Он содержит бесконечный цикл, который не делает ничего, чтобы вырваться из цикла. Тебе необходимо break
или return
где-то внутри цикла, если вы хотите перейти к следующему шагу в вашем приложении.
Как только вы это сделаете, ваш следующий звонок run_forever
, который, как следует из его названия, будет работать вечно. И в этом случае с этим ничего не поделаешь, потому что вы ничего не запланировали с помощью цикла обработки событий.
Я ожидал, что сопрограмма будет выполнена только один раз, потому что она содержит выход и должна была вернуть управление вызывающей стороне.
Если посмотреть на тот факт, что ваша сопрограмма не имеет выхода, ожидание (или уступка в зависимости от того, какой синтаксис вы выберете) не возвращает управление вызывающей стороне run_until_complete
или же run_forever
, Он возвращает управление в цикл обработки событий, так что он может проверять все, что ожидалось и готово возобновить.