使用PhaseMap包遇asyncio事件循环已运行错误求修复方案
问题描述
我正尝试使用PhaseMap这个Python包,但官方教程中的最小可运行示例无法正常执行:
import phasemap as pm def phase(pos): x, y = pos return int(x**2 + y**2 < 1) res = pm.run( phase, limits=[(-1, 1), (-1, 1)], mesh=3, )
在Python 3.11.9环境下运行该代码时,触发如下错误:
File ~/Desktop/repos/non_linear_topological_invariants/nonlinear_topological_invariants/lib/python3.11/site-packages/phasemap-1.0.0-py3.11.egg/phasemap/_run.py:103, in run(fct, limits, mesh, num_steps, all_corners, init_result, save_file, load, load_quiet, serializer, save_interval) 90 else: 91 init_points = None 93 return _RunImpl( 94 fct=fct, 95 limits=limits, 96 mesh=mesh, 97 num_steps=num_steps, 98 all_corners=all_corners, 99 init_points=init_points, 100 save_file=save_file, 101 serializer=serializer, 102 save_interval=save_interval, --> 103 ).execute() File ~/Desktop/repos/non_linear_topological_invariants/nonlinear_topological_invariants/lib/python3.11/site-packages/phasemap-1.0.0-py3.11.egg/phasemap/_run.py:158, in _RunImpl.execute(self) 157 def execute(self): --> 158 self._loop.run_until_complete(self._run()) 159 return self.result File ~/.pyenv/versions/3.11.9/lib/python3.11/asyncio/base_events.py:630, in BaseEventLoop.run_until_complete(self, future) 619 """Run until the Future is done. 620 621 If the argument is a coroutine, it is wrapped in a Task. (...) 627 Return the Future's result, or raise its exception. 628 """ 629 self._check_closed() --> 630 self._check_running() 632 new_task = not futures.isfuture(future) 633 future = tasks.ensure_future(future, loop=self) File ~/.pyenv/versions/3.11.9/lib/python3.11/asyncio/base_events.py:589, in BaseEventLoop._check_running(self) 587 def _check_running(self): 588 if self.is_running(): --> 589 raise RuntimeError('This event loop is already running') 590 if events._get_running_loop() is not None: 591 raise RuntimeError( 592 'Cannot run the event loop while another loop is running') RuntimeError: This event loop is already running
该问题似乎与asyncio库的实现相关,但不知如何修复,请问是否有针对该包的直接修复方案?
解决方案
这个错误是因为PhaseMap内部的asyncio事件循环管理在Python 3.11+环境下和已有运行中的事件循环冲突导致的,以下是几种直接修复方案:
方案1:修改PhaseMap源码适配事件循环
找到安装的PhaseMap包中的phasemap/_run.py文件,修改execute方法:
- 原代码:
def execute(self): self._loop.run_until_complete(self._run()) return self.result
- 替换为:
import asyncio import nest_asyncio def execute(self): try: loop = asyncio.get_running_loop() if loop.is_running(): nest_asyncio.apply() task = loop.create_task(self._run()) loop.run_until_complete(task) else: self._loop.run_until_complete(self._run()) except RuntimeError: self._loop.run_until_complete(self._run()) return self.result
执行前先安装依赖包:pip install nest_asyncio
方案2:手动用异步模式调用(不修改包源码)
直接在自己的代码中绕开pm.run的事件循环冲突问题:
import phasemap as pm import asyncio import nest_asyncio def phase(pos): x, y = pos return int(x**2 + y**2 < 1) async def run_phasemap(): runner = pm._RunImpl( fct=phase, limits=[(-1, 1), (-1, 1)], mesh=3, ) await runner._run() return runner.result nest_asyncio.apply() res = asyncio.run(run_phasemap())
方案3:降级Python版本
如果不想修改代码或添加依赖,可以暂时降级到Python 3.10及以下版本,该版本的asyncio事件循环检测逻辑不会触发这个错误。
内容的提问来源于stack exchange,提问作者Kieran Cooney
相关产品推荐
相关产品推荐

