在异步函数内的同步函数内运行异步函数
Posted
技术标签:
【中文标题】在异步函数内的同步函数内运行异步函数【英文标题】:run async function inside sync function inside async function 【发布时间】:2021-08-19 09:11:35 【问题描述】:这是我遇到的问题的简化方案。
import asyncio
async def c():
print("yes")
def b():
asyncio.run(c())
async def a():
b()
asyncio.run(a())
我希望程序打印“是”。但是,我得到了这个:
Traceback (most recent call last):
File [redacted], line 12, in <module>
asyncio.run(a())
File "/usr/lib64/python3.7/asyncio/runners.py", line 43, in run
return loop.run_until_complete(main)
File "/usr/lib64/python3.7/asyncio/base_events.py", line 579, in run_until_complete
return future.result()
File [redacted], line 10, in a
b()
File [redacted], line 7, in b
asyncio.run(c())
File "/usr/lib64/python3.7/asyncio/runners.py", line 34, in run
"asyncio.run() cannot be called from a running event loop")
RuntimeError: asyncio.run() cannot be called from a running event loop
sys:1: RuntimeWarning: coroutine 'c' was never awaited
你认为解决这个问题的方法是什么?
(另外,这可以使用纯异步来完成吗?)
【问题讨论】:
为什么需要这样做?您的用例是什么,因为它们可能是更好的解决方案。 对此没有合适的解决方案。即使你在技术上可以做到这一点,你真的,真的不应该 - 它会阻塞外部事件循环,即使在最好的情况下也会使异步的任何好处无效。 请edit您的问题澄清问题的约束。现在,“正确”的解决方案就是删除 b。 b是否需要C的返回值? b 可以变成异步函数吗? c 必须在 b 期间完成吗? b是否需要在主线程中运行,c是否需要在主事件循环中运行? 【参考方案1】:不要在同一个程序中调用 asyncio.run() 两次。相反,一旦事件循环运行,创建一个任务并等待它。同步函数可以创建一个新任务但不能等待它;它可以将它作为等待返回。然后异步调用函数可以执行等待。
import asyncio
async def c():
print("yes")
def b():
return asyncio.create_task(c())
async def a():
task = b()
await task
asyncio.run(a())
>>>yes
【讨论】:
这里不需要任务。 b 可以直接返回 c()。 是的。但是除非在某处创建了第二个任务,否则根本不需要 asyncio。这似乎是问题所在,因为第二次尝试调用 run()。以上是关于在异步函数内的同步函数内运行异步函数的主要内容,如果未能解决你的问题,请参考以下文章