2025, Nov 01 03:17
Phasemap в Jupyter: как исправить RuntimeError с nest_asyncio
Почему phasemap в Jupyter падает с RuntimeError "This event loop is already running" и как решить: используйте nest_asyncio для стабильной работы asyncio.
Запуск минимального примера phasemap в Jupyter может неожиданно завершиться с ошибкой RuntimeError о уже запущенном цикле событий. Сам код корректен; конфликт возникает из‑за того, как внутри используется asyncio. Ниже — короткое объяснение проблемы и практичное решение, которое стабильно работает в ноутбуках.
Как воспроизвести проблему
Ниже приведён минимальный пример, повторяющий официальный туториал, лишь с другими именами. Он вычисляет простую индикаторную функцию на квадратной области и передаёт её в 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,
)
При выполнении в Python 3.11.9 в Jupyter или JupyterLab это может привести к ошибке:
RuntimeError: This event loop is already running
Почему так происходит
phasemap использует asyncio и цикл событий для управления выполнением. В Jupyter свой цикл уже запущен — он обслуживает асинхронность ноутбука. Запустить ещё один цикл в том же потоке нельзя, из‑за чего и появляется RuntimeError. Тот же код, запущенный как обычный скрипт Python (например, через python script.py в терминале), не пересекается с циклом Jupyter и потому работает штатно.
Решение
Самый простой способ подружить phasemap с циклом событий Jupyter — разрешить вложенные циклы. Пакет nest_asyncio патчит уже работающий цикл, чтобы код, запускающий собственные задачи через asyncio, выполнялся без конфликта.
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)
Достаточно один раз вызвать nest_asyncio.apply() в текущей сессии ядра — после этого код без проблем запускается в Jupyter и ведёт себя так же, как задумано изначально.
Зачем это знать
Среды ноутбуков часто скрывают детали исполнения, на которые опираются библиотеки. Если пакет внутри использует asyncio, уже запущенный в ноутбуке цикл событий проявляет себя только во время выполнения, и сообщение об ошибке может казаться не по теме. Осознание, что такой сценарий в Jupyter типичен, помогает быстро отличить баги в коде от ограничений окружения и применить безопасный обходной путь, не трогая саму библиотеку.
Итоги
Если phasemap.run в Jupyter выдаёт “This event loop is already running”, это конфликт циклов событий, а не проблема алгоритма. Либо запускайте тот же код как обычный Python‑скрипт — там всё работает, либо пропатчьте цикл в ноутбуке с помощью nest_asyncio, чтобы обе части сосуществовали. Такой подход сохраняет плавность рабочего процесса и не меняет исходную логику пакета.
Статья основана на вопросе на StackOverflow от Kieran Cooney и ответе от furas.