我试图在同步上下文中找到一个调用异步函数的解决方案。
以下是我的参考资料:
但是我发现,asyncio.get_event_loop()在跟踪asyncio.run()时失败了,下面是我的代码来重现这个问题:
import asyncio
async def asyncfunction(n):
print(f'before sleep in asyncfunction({ n })')
await asyncio.sleep(1)
print(f'after sleep in asyncfunction({ n })')
return f'result of asyncfunction({ n })'
def callback(r):
print(f'inside callback, got: {r}')
r0 = asyncio.run(asyncfunction(0)) # cause following asyncio.get_event_loop() fail.
callback(r0)
print('sync code following asyncio.run(0)')
r1 = asyncio.run(asyncfunction(1)) # but following asyncio.run() still works.
callback(r1)
print('sync code following asyncio.run(1)')
async def wrapper(n):
r = await asyncfunction(n)
callback(r)
asyncio.get_event_loop().create_task(wrapper(2)) #fail if there is asyncio.run() before
print('sync code following loop.create_task(2)')
#RuntimeError: There is no current event loop in thread 'MainThread'.
asyncio.get_event_loop().create_task(wrapper(3)) #the second call works if there is no asyncio.run() before
print('sync code following loop.create_task(3)')
# main
_all = asyncio.gather(*asyncio.all_tasks(asyncio.get_event_loop()))
asyncio.get_event_loop().run_until_complete(_all)我认为这可能是因为事件循环被某种东西“消耗”了,而asyncio.set_event_loop(asyncio.new_event_loop())可能是一种解决办法,但我不确定是否是最终用户手动设置事件循环的预期用法。我也在想,为什么,和,一切是如何发生的,。
在阅读了一些asyncio.run的源代码之后。我知道为什么会这样。
但是我仍然在想,在同步上下文中调用异步函数的预期方式是什么?
下面的代码似乎可以工作(在每次asyncio.run()调用之后设置一个新的事件循环):
asyncio.run(asyncfunction())
asyncio.set_event_loop(asyncio.new_event_loop())但这有点奇怪,似乎并不是人们期望的方式。
发布于 2021-12-03 13:13:55
当您调用asyncio.run时,它每次调用它都会创建一个新的事件循环。该事件循环随后在asyncio.run完成时被销毁。因此,在第二个asyncio.run完成后的代码示例中,根本没有事件循环,您以前创建的两个事件循环不再存在。asyncio.get_event_loop通常会为您创建一个新的事件循环,除非以前调用了set_event_loop,而asyncio.run确实这样做(这说明了如果删除asyncio.run的话,为什么会工作)。要修复您的代码,您应该创建一个新的事件循环,只使用它而不是调用get_event_loop,记住这是第三个循环,这可能不是您想要的。
import asyncio
async def asyncfunction(n):
print(f'before sleep in asyncfunction({ n })')
await asyncio.sleep(1)
print(f'after sleep in asyncfunction({ n })')
return f'result of asyncfunction({ n })'
def callback(r):
print(f'inside callback, got: {r}')
r0 = asyncio.run(asyncfunction(0))
callback(r0)
print('sync code following asyncio.run(0)')
r1 = asyncio.run(asyncfunction(1))
callback(r1)
print('sync code following asyncio.run(1)')
async def wrapper(n):
r = await asyncfunction(n)
callback(r)
loop = asyncio.new_event_loop()
loop.create_task(wrapper(2))
print('sync code following loop.create_task(2)')
loop.create_task(wrapper(3))
print('sync code following loop.create_task(3)')
# main
_all = asyncio.gather(*asyncio.all_tasks(loop))
loop.run_until_complete(_all)https://stackoverflow.com/questions/70214433
复制相似问题