Report #30059
[bug\_fix] Asyncio Event Loop Conflict on Import in Jupyter/REPL
Refactor to avoid calling \`asyncio.run\(\)\` or \`get\_event\_loop\(\)\` at module import time; instead expose an entry point function. For Jupyter notebooks specifically, apply \`nest\_asyncio.apply\(\)\` at the notebook start. The root cause is that Jupyter \(and IPython\) already runs an asyncio event loop in the main thread to handle async kernel operations. When a library or user code calls \`asyncio.run\(\)\` during import \(module-level side effects\) or in a cell, Python raises \`RuntimeError: asyncio.run\(\) cannot be called from a running event loop\` because \`asyncio.run\(\)\` creates a new loop and must be called when no loop is running in the main thread.
Journey Context:
You're developing a data pipeline using \`asyncio\` and \`aiohttp\`. You create \`client.py\` with \`import asyncio\` and at module level you define \`loop = asyncio.get\_event\_loop\(\)\` or call \`asyncio.run\(setup\(\)\)\` to initialize a connection pool. You test it in a standalone script with \`if \_\_name\_\_ == '\_\_main\_\_': asyncio.run\(main\(\)\)\` and it works. Later, you open a Jupyter Notebook to prototype and run \`from client import MyClient\`. Immediately you get \`RuntimeError: This event loop is already running\` or \`asyncio.run\(\) cannot be called from a running event loop\`. You debug with \`asyncio.get\_running\_loop\(\)\` and confirm Jupyter already has an active loop in the main thread. You realize your import-time side effect \(\`get\_event\_loop\(\)\` or \`asyncio.run\(\)\`\) is executing during the import statement, conflicting with Jupyter's running loop. You search for solutions and find \`nest\_asyncio\` which patches the loop to allow nesting, or you refactor \`client.py\` to use lazy initialization \(create the loop/client inside functions/methods rather than at module level\). After moving the \`asyncio.run\(\)\` call into a \`if \_\_name\_\_ == '\_\_main\_\_':\` guard and removing module-level loop creation, the import in Jupyter succeeds because no conflicting loop operations occur at import time.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T04:50:37.578986+00:00— report_created — created