В этом случае ответ лежит в документации, но вы должны немного поискать его.Во-первых, напоминание о том, что означает ожидание будущего:
# the expression:
x = await future
# is equivalent to:
... magically suspend the coroutine until the future.done() becomes true ...
x = future.result()
Другими словами, после возобновления выполнения сопрограммы, содержащей await
, значение *Заявление 1007 * будет result()
ожидаемого будущего.
Вопрос: когда вы отменяете будущее, каков его результат? документация гласит:
Если будущее было отменено , этот метод вызывает исключение CancelledError
.
Поэтому, когда кто-то отменяет ожидаемое вами будущее, выражение await future
вызовет исключение!Это четко объясняет, почему bar
не печатает hi
(потому что await future
поднял), и почему baz
не печатает ho
(потому что await bar(...)
поднялось).
Обратная трассировка никогда не печатается, потому что loop.create_task
порождает сопрограмму в «фоне» (своего рода) - если никто не проверяет возвращаемое значение, исключение будет потеряно.А поскольку вы выбросили объект task , возвращаемый create_task
, и использовали run_forever
, чтобы цикл работал вечно, цикл просто продолжает работать, ожидая (навсегда) новых задач, которые каким-то образом поступят.
Если вы изменили код для фактического сбора результата bar
, вы легко могли бы наблюдать вывод CancelledError
:
if __name__ == '__main__':
loop = asyncio.get_event_loop()
future = loop.create_future()
loop.create_task(foo(future))
loop.run_until_complete(baz(future))
:
Traceback (most recent call last):
File "xxx.py", line 19, in <module>
loop.run_until_complete(baz(future))
File "/usr/lib/python3.5/asyncio/base_events.py", line 387, in run_until_complete
return future.result()
File "/usr/lib/python3.5/asyncio/futures.py", line 266, in result
raise CancelledError
concurrent.futures._base.CancelledError