【发布时间】:2020-09-09 13:01:00
【问题描述】:
import asyncio
def add_world_task():
loop = asyncio.get_running_loop()
loop.call_soon(print_world)
# asyncio.create_task(print_world()) # <-- This is a "fix",
async def print_hello():
print("hello!")
add_world_task()
async def print_world():
print("world!")
loop = asyncio.new_event_loop()
loop.run_until_complete(print_hello())
以下代码将运行并警告print_world 协程未运行:
hello!
/usr/lib/python3.7/asyncio/events.py:88: RuntimeWarning: coroutine 'print_world' was never awaited
self._context.run(self._callback, *self._args)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Process finished with exit code 0
这对我来说很有意义,根据call_soon 的文档,放置在call_soon 中的回调将在事件循环的下一次迭代中运行。 run_until_complete 一直运行直到方法完成。因此,一旦print_hello 完成,事件循环就不会再次迭代,协程print_world 不会运行。
我不明白为什么asyncio.create_task(print_world()) 在给定run_until_complete 定义的情况下成功运行。一旦print_hello 完成,协程print_world 似乎仍设法在事件循环中运行,这与run_until_complete 的文档相对?
这是因为call_soon 将协程放在事件循环的开头,create_task 将它放在后面 - 而run_until_complete 实际完成了当前任务和剩余部分事件循环迭代?
(您可能会觉得我使用同步 add_world_task 而不是直接使用 await print_world 很奇怪。不幸的是,这很像我的真实场景。我有一个同步方法(Django 信号方法)需要运行异步方法,而事件循环可能已经在运行。它可以通过向正在运行的事件循环添加协程来做到这一点)
【问题讨论】: