2025, Oct 29 09:00
How to Run phasemap in Jupyter Without RuntimeError: enable asyncio loop nesting via nest_asyncio
Learn why phasemap.run fails in Jupyter with 'This event loop is already running' RuntimeError and fix it by applying nest_asyncio to enable loop nesting.
Running phasemap’s minimal example in Jupyter can unexpectedly fail with a RuntimeError about an already running event loop. The code itself is fine; the conflict comes from how asyncio is used under the hood. Here is a concise walkthrough of the issue and a pragmatic fix that works reliably in notebooks.
Reproducing the problem
The following minimal sample mirrors the official tutorial, only with different identifiers. It computes a simple indicator function over a square domain and passes it to phasemap.run.
import phasemap as ph
def label(pt):
    a, b = pt
    return int(a**2 + b**2 < 1)
result = ph.run(
    label,
    limits=[(-1, 1), (-1, 1)],
    mesh=3,
)
When executed in Python 3.11.9 inside Jupyter or JupyterLab, this can raise:
RuntimeError: This event loop is already running
What’s going on
phasemap uses asyncio with an event loop to drive its execution. Jupyter already runs its own event loop to handle the notebook’s asynchronous operations. Starting another loop in the same thread is not allowed, which triggers the RuntimeError. Running exactly the same code as a plain Python script (for example, via python script.py in a terminal) does not collide with Jupyter’s loop and therefore works as expected.
Solution
The most straightforward way to make phasemap coexist with Jupyter’s event loop is to enable loop nesting. The nest_asyncio package patches the running loop so that code starting its own asyncio orchestration can proceed without raising the conflict.
import nest_asyncio
nest_asyncio.apply()
import phasemap as ph
def label(pt):
    a, b = pt
    return int(a**2 + b**2 < 1)
outcome = ph.run(
    label,
    limits=[(-1, 1), (-1, 1)],
    mesh=3,
)
print(outcome)
With nest_asyncio.apply() executed once per kernel session, the code runs cleanly in Jupyter while preserving the original behavior.
Why this matters
Notebook environments often abstract away the runtime details that libraries rely on. When a package uses asyncio internally, the notebook’s pre-existing event loop can become visible only at runtime, and the error message may look unrelated to the actual task. Knowing that this pattern is typical in Jupyter helps quickly distinguish code bugs from environment constraints and apply a safe workaround without touching the library itself.
Takeaways
If phasemap.run raises “This event loop is already running” in Jupyter, it’s an event loop collision rather than an issue with the algorithm. Either execute the same code as a standard Python script, where it runs fine, or patch the loop in the notebook with nest_asyncio to let both coexist. This keeps your workflow smooth while staying faithful to the intended behavior of the package.
The article is based on a question from StackOverflow by Kieran Cooney and an answer by furas.