【问题标题】:RuntimeError: asyncio.run() cannot be called from a running event loopRuntimeError:无法从正在运行的事件循环中调用 asyncio.run()
【发布时间】:2019-10-02 21:11:45
【问题描述】:

我正在尝试了解 websockets 客户端的 asyncio。我尝试的每段代码都会出现以下错误:

RuntimeError: asyncio.run() 不能从正在运行的事件循环中调用

我尝试了最简单的代码,但它总是给出 RuntimeError。我尝试再次安装完整的 anaconda 发行版等,但找不到问题所在。

我将 Spyder 3.3.3 与 Python 3.7.3 一起使用

应该工作的代码示例:

import asyncio

async def main():
    print('hello')
    await asyncio.sleep(1)
    print('world')

asyncio.run(main())

错误信息:

File "C:\Users\jmart\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 786, in runfile
  execfile(filename, namespace)
File "C:\Users\jmart\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 110, in execfile
  exec(compile(f.read(), filename, 'exec'), namespace)
File "C:/Users/jmart/Documents/asynk2.py", line 8, in <module>
  asyncio.run(main())
File "C:\Users\jmart\Anaconda3\lib\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

【问题讨论】:

  • 您是否尝试从输入python3.7 asynk2.py 的终端运行代码?我的猜测是 Spyder 正在使用事件循环来运行它的 python 控制台/解释器,这导致了这个问题......
  • 非常感谢,好像是这个问题,有什么办法可以解决吗?
  • 添加import nest_asyncionest_asyncio.apply() 似乎是一种解决方案
  • 这是this的副本吗?

标签: python python-asyncio python-3.7


【解决方案1】:

它是与 IPython 相关的 a known problem

One way 你已经发现是使用nest_asyncio:

import nest_asyncio
nest_asyncio.apply()

The other one 是安装旧版本的tornado

pip3 install tornado==4.5.3

【讨论】:

  • 第一个解决方案似乎给我带来了一些运行问题,安装旧版本的龙卷风似乎完美无缺!
  • 当心,嵌套的运行调用会饿死循环。这个猴子补丁在 python / stdlib 升级时非常脆弱。
  • 有什么理由不简单地将await main()与spyder一起使用?
【解决方案2】:

问题根源

Spyder 运行自己的事件循环

print(asyncio.get_running_loop().is_running()) 
Returns: True

但每个线程只允许一个

cannot be called when another asyncio event loop is running in the same thread

这就是为什么当我们尝试使用
asyncio.run(main()) 创建一个新的事件循环时,它会给我们一个错误:
RuntimeError: asyncio.run() cannot be called from a running event loop

解决方案

除了我已经提出的 Nest_asyncio 和 tornado 的建议

  1. 通过创建新任务附加到现有的 Spyder 线程事件循环
import asyncio

async def main():
    print('Hello world!')

asyncio.create_task(main())
  1. 创建允许运行我们自己的事件循环的新线程(通过在外部终端中执行)。
    顶部菜单运行 -> 运行每个文件的配置... -> 在外部系统终端中执行

现在代码在新终端中运行并正常工作

import asyncio

async def main():
    print('Hello world!')
asyncio.run(main())

【讨论】:

  • 这绝对是更好的答案。完美将是带有try: ....create_task(main()) except RuntimeError: asyncio.run(main()) 的独立于解释器的版本。这在 Spyder 中运行良好,但在 python shell 中仍然会产生一些警告:(
猜你喜欢
  • 1970-01-01
  • 2022-11-25
  • 2020-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-17
  • 1970-01-01
相关资源
最近更新 更多