pythondebuggingpython-asyncio

Python async issue with PhaseMap package


PhaseMap is a python package I am trying to use, but the minimal working example in the tutorial isn't working:

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,
)

When I run this code (on Python 3.11.9), the following error is raised:

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

This seems like a straightforward issue with the implementation of the asyncio library, but I don't know how to fix it. Is there a straightforward fix to this package that will solve the issue?

Thanks!


Solution

  • It seems phasemap uses asyncio and event loop to run some code.

    If you run it in Jupyter then problem is because Jupyter aready is running asyncio with event loop but it can't start another loop in the same thread. It seems it would need to start it in separate thread.

    But I found module nest_asyncio which resolves this problem (at least in this code).

    import nest_asyncio
    
    nest_asyncio.apply()
    
    import phasemap as pm
    
    def phase(pos):
        x, y = pos
        #print(x, y)
        return int(x**2 + y**2 < 1)
    
    res = pm.run(
        phase,
        limits=[(-1, 1), (-1, 1)],
        mesh=3,
    )
    
    print(res)