繁体   English   中英

跟随 asyncio.run() 时 asyncio.get_event_loop() 失败

[英]asyncio.get_event_loop() fails when following asyncio.run()

我正在尝试找到一种解决方案来在同步上下文中调用 async function

以下是我的参考资料:

但我发现, 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的一些源代码之后。 我可以知道为什么会这样。

但我仍然想知道在同步上下文中调用异步 function 的预期方式是什么

似乎以下代码有效(在每次asyncio.run()调用后设置一个新的事件循环):

asyncio.run(asyncfunction()) 
asyncio.set_event_loop(asyncio.new_event_loop())

但这有点奇怪,而且似乎不是预期的方式。

当您调用asyncio.run时,每次调用它都会创建一个新的事件循环。 asyncio.run完成时,该事件循环随后被销毁。 因此,在您的第二个asyncio.run完成后的代码示例中,根本没有事件循环,您之前创建的两个不再存在。 asyncio.get_event_loop通常会为你创建一个新的事件循环,除非之前调用了set_event_loopasyncio.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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM