首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >asyncio.get_event_loop()在跟随asyncio.run()时失败

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

Stack Overflow用户
提问于 2021-12-03 12:37:30
回答 1查看 1.6K关注 0票数 0

我试图在同步上下文中找到一个调用异步函数的解决方案。

以下是我的参考资料:

但是我发现,asyncio.get_event_loop()在跟踪asyncio.run()时失败了,下面是我的代码来重现这个问题:

代码语言:javascript
复制
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()调用之后设置一个新的事件循环):

代码语言:javascript
复制
asyncio.run(asyncfunction()) 
asyncio.set_event_loop(asyncio.new_event_loop())

但这有点奇怪,似乎并不是人们期望的方式。

EN

回答 1

Stack Overflow用户

发布于 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,记住这是第三个循环,这可能不是您想要的。

代码语言:javascript
复制
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)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70214433

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档