问题描述
import asyncio
async def print_number(num):
if num % 2 == 0:
await asyncio.sleep(1)
print(num)
def add_tasks():
current_loop = asyncio.get_running_loop()
for i in range(10):
current_loop.create_task(print_number(i))
async def print_hello():
print("Hello World!")
add_tasks()
asyncio.get_event_loop().run_until_complete(print_hello())
# asyncio.get_event_loop().run_until_complete(asyncio.sleep(1.1))
Hello World!
1
3
5
7
9
Process finished with exit code 0
起初,这使我感到惊讶,因为给出了奇数,但是在await
之后完成的偶数却没有。取消对sleep
行的注释会显示它们。
在asycio中读取以下代码说明了原因:使用create_task
添加任务可确保一旦循环完成迭代,则在事件循环结束时调用它们,但计划进行任何回调/唤醒直到下一次事件循环迭代时才会执行这些操作-不会发生,因为print_hello()
现在已经结束,run_until_complete
终止了。
在那种情况下,是否有办法同步(没有await
)将协程添加到已经运行的事件循环中并确保执行?如上所述,以上代码无法确保其执行。
在我的实际场景中,add_tasks
是一种同步方法,我无法更改其方法签名,只能更改add_tasks
的方法内容。我也无法控制事件循环的开始方式。
在这一点上,我正在考虑使用其自己的事件循环启动一个新线程,在其中执行协程,并.join()
等待其执行。但是有更好的方法吗?
对于上下文...为什么需要这个可能看起来很奇怪,但是不幸的是,这对我来说是一个真实的情况。我在Django信号中,它是一种同步方法,但可能在事件循环中运行(这是一个信号,非常通用的一段代码)。该信号需要运行channel_layer.group_send
包提供的异步方法channels
。因此,我必须将channel_layer.group_send
同步附加到事件循环中(async_to_sync
不起作用,因为它会引发异常,告诉您await
如果您处于事件循环中)。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)