Notebook kernels own the event loop; async code must cooperate with that ownership rather than fight it.
This skill covers orchestration patterns, top-level await, and compatibility constraints for .ipynb and #%% workflows.
Treat these recommendations as preferred defaults.
When project constraints require deviation, call out tradeoffs and compensating controls.
When to Use
asyncio.run() raises RuntimeError inside a notebook cell.
Event-loop conflicts when mixing async libraries in Jupyter.
Porting async scripts into notebook workflows.
Orchestrating concurrent tasks (gather, TaskGroup) in IPython kernels.
Deciding where to place reusable async logic across notebook/module boundaries.
When NOT to Use
Pure script or service code with no notebook involvement — see python-concurrency-performance.
Synchronous notebook workflows with no async needs.
General asyncio API design outside notebook contexts — see python-runtime-operations.
Quick Reference
Treat notebook kernels as loop-owned environments; never create a competing loop.
Use top-level await instead of asyncio.run() in notebook cells.
Orchestrate concurrent work with asyncio.gather() or asyncio.TaskGroup.
Keep reusable async logic in regular .py modules, imported into notebooks.
Use nest_asyncio only as a constrained compatibility fallback, not a default.
Avoid fire-and-forget tasks — always await or collect results explicitly.
Common Mistakes
Calling asyncio.run() in a notebook cell.
The kernel already runs a loop; asyncio.run() tries to start a second one and raises RuntimeError.
Use await directly instead.
Applying nest_asyncio globally by default.
It patches the loop to allow reentrant calls but masks design problems and can hide subtle concurrency bugs.
Reserve it for legacy compatibility.
Defining async helpers inline in cells instead of modules.
Inline definitions are lost on kernel restart and cannot be tested outside the notebook.
Extract to .py files.
Ignoring returned tasks or coroutines.
Calling an async function without await silently produces a never-executed coroutine object, with no error until results are missing downstream.
Mixing blocking I/O with async in the same cell.
Synchronous calls like requests.get() block the event loop, starving concurrent tasks.
Use aiohttp, httpx, or asyncio.to_thread().
Scope Note
Treat these recommendations as preferred defaults for common cases, not universal rules.
If a default conflicts with project constraints or worsens the outcome, suggest a better-fit alternative and explain why it is better for this case.
When deviating, call out tradeoffs and compensating controls (tests, observability, migration, rollback).
Invocation Notice
Inform the user when this skill is being invoked by name: python-design-modularity.
References
references/notebooks-async.md
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
1---2name: ahgraber-skills-python-notebooks-async3description: Python Notebooks Async4---56# Python Notebooks Async78## Overview910Notebook kernels own the event loop; async code must cooperate with that ownership rather than fight it.11This skill covers orchestration patterns, top-level `await`, and compatibility constraints for `.ipynb` and `#%%` workflows.1213Treat these recommendations as preferred defaults.14When project constraints require deviation, call out tradeoffs and compensating controls.1516## When to Use1718- `asyncio.run()` raises `RuntimeError` inside a notebook cell.19- Event-loop conflicts when mixing async libraries in Jupyter.20- Porting async scripts into notebook workflows.21- Orchestrating concurrent tasks (`gather`, `TaskGroup`) in IPython kernels.22- Deciding where to place reusable async logic across notebook/module boundaries.2324### When NOT to Use2526- Pure script or service code with no notebook involvement — see `python-concurrency-performance`.27- Synchronous notebook workflows with no async needs.28- General asyncio API design outside notebook contexts — see `python-runtime-operations`.2930## Quick Reference3132- Treat notebook kernels as loop-owned environments; never create a competing loop.33- Use top-level `await` instead of `asyncio.run()` in notebook cells.34- Orchestrate concurrent work with `asyncio.gather()` or `asyncio.TaskGroup`.35- Keep reusable async logic in regular `.py` modules, imported into notebooks.36- Use `nest_asyncio` only as a constrained compatibility fallback, not a default.37- Avoid fire-and-forget tasks — always `await` or collect results explicitly.3839## Common Mistakes4041- **Calling `asyncio.run()` in a notebook cell.**42 The kernel already runs a loop; `asyncio.run()` tries to start a second one and raises `RuntimeError`.43 Use `await` directly instead.44- **Applying `nest_asyncio` globally by default.**45 It patches the loop to allow reentrant calls but masks design problems and can hide subtle concurrency bugs.46 Reserve it for legacy compatibility.47- **Defining async helpers inline in cells instead of modules.**48 Inline definitions are lost on kernel restart and cannot be tested outside the notebook.49 Extract to `.py` files.50- **Ignoring returned tasks or coroutines.**51 Calling an async function without `await` silently produces a never-executed coroutine object, with no error until results are missing downstream.52- **Mixing blocking I/O with async in the same cell.**53 Synchronous calls like `requests.get()` block the event loop, starving concurrent tasks.54 Use `aiohttp`, `httpx`, or `asyncio.to_thread()`.5556## Scope Note5758- Treat these recommendations as preferred defaults for common cases, not universal rules.59- If a default conflicts with project constraints or worsens the outcome, suggest a better-fit alternative and explain why it is better for this case.60- When deviating, call out tradeoffs and compensating controls (tests, observability, migration, rollback).6162## Invocation Notice6364- Inform the user when this skill is being invoked by name: `python-design-modularity`.6566## References6768- `references/notebooks-async.md`6970---71> Converted and distributed by [TomeVault](https://tomevault.io/claim/ahgraber) — claim your Tome and manage your conversions.72<!-- tomevault:4.0:skill_md:2026-04-11 -->
Run npx skillmds@latest add tomevault-io/ahgraber-skills-python-notebooks-async in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Python Notebooks Async It is listed under Coding & Dev Tools on SkillMD.
This skill has not completed SkillMD's automated safety review yet. Independent scanners report: SkillSpector: PASS, Skill Scanner: PASS. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
tomevault-io (@tomevault-io) published this skill. Their other Agent Skills are listed on their SkillMD profile.