asyncio (PyPI backport)
raw JSON → 4.0.0 verified Tue May 12 auth: no python install: verified deprecated
The `asyncio` package on PyPI (version 4.0.0) is a deprecated backport of the `asyncio` module, which has been part of Python's standard library since Python 3.4. This PyPI distribution is no longer needed and serves primarily to prevent accidental installation of outdated backports. Users should *not* install this package and instead rely on the built-in `asyncio` module provided by their Python installation.
pip install asyncio Common errors
error RuntimeWarning: coroutine 'foo' was never awaited ↓
cause This warning occurs when a coroutine is defined but not awaited, meaning the coroutine is created but never executed.
fix
Ensure that all coroutines are awaited using the 'await' keyword: 'await foo()'.
error RuntimeError: This event loop is already running ↓
cause This error arises when attempting to run a new event loop while another one is already running, often in environments like Jupyter notebooks.
fix
Use 'await' directly in Jupyter notebooks instead of 'asyncio.run()' to avoid nested event loops.
error Task was destroyed but it is pending! ↓
cause This warning indicates that an asyncio Task was garbage collected before it had a chance to complete, often due to not keeping a reference to the Task.
fix
Keep a reference to the Task until it completes, for example by storing it in a variable or a list.
error AttributeError: module 'asyncio' has no attribute 'run' ↓
cause This error occurs when trying to use 'asyncio.run()' in Python versions prior to 3.7, where this function is not available.
fix
For Python versions before 3.7, use 'loop = asyncio.get_event_loop()' and 'loop.run_until_complete()' to run coroutines.
error RuntimeError: Event loop is closed ↓
cause This error happens when an operation is attempted on an event loop that has already been closed.
fix
Ensure that the event loop is open before performing operations, and avoid closing the loop prematurely.
Warnings
breaking The `asyncio` package on PyPI is an obsolete backport for Python versions prior to 3.4. Installing it on modern Python (3.4+) can conflict with and break the standard library `asyncio` due to `sys.path` order. Version 4.0.0 and above of the PyPI package contain no code and exist solely to prevent accidental installation of outdated backports; it *should not be installed*. ↓
fix Do not install `asyncio` from PyPI. Remove it if already installed (`pip uninstall asyncio`) and rely on Python's standard library version.
deprecated The `@asyncio.coroutine` decorator for defining coroutines was deprecated in Python 3.8 and completely removed in Python 3.10. Using it will result in `SyntaxError` or `DeprecationWarning` depending on the Python version. ↓
fix Always use the `async def` syntax for defining coroutines (e.g., `async def my_coroutine(): ...`).
gotcha A very common mistake is calling an `async def` function without `await`ing it. This creates a coroutine object but does not schedule or run it, leading to silent bugs or unexpected behavior (e.g., the code inside the coroutine never executes). ↓
fix Always use `await` when calling an awaitable from within a coroutine (e.g., `await my_coroutine()`). If scheduling a task concurrently, use `asyncio.create_task()` or `asyncio.TaskGroup` and then await the task/group.
gotcha `asyncio.run()` cannot be called when an event loop is already running in the current thread. This is a common issue in interactive environments like Jupyter notebooks or when attempting to nest `asyncio.run()` calls. ↓
fix In interactive shells or environments with a running event loop, `await` coroutines directly or use a mechanism like `nest_asyncio` (with caution in Python 3.14+). Avoid nested `asyncio.run()` calls; structure your application to have a single top-level entry point.
breaking Python 3.12 introduced significant changes to `asyncio` affecting task management, exception handling within `TaskGroup`, and cancellation behavior. The `asyncio.get_event_loop()` function became stricter, and `asyncio.run()` now explicitly ensures the event loop and associated resources (like executors and async generators) are properly shut down by default. Code relying on low-level event loop interactions or specific task behavior might encounter breaking changes. ↓
fix Review and update code that interacts directly with event loop policies, relies on implicit loop creation, or has specific exception/cancellation handling, especially when upgrading from Python 3.11 or older. Adopt `asyncio.TaskGroup` for improved structural concurrency and error handling.
breaking Python 3.14 changed `asyncio`'s internal implementation in ways that break previous workarounds for nested event loops, notably affecting libraries like `nest_asyncio`. This primarily impacts environments like Jupyter notebooks where an event loop is already active, preventing the automatic async-to-sync conversion previously offered by such workarounds. ↓
fix In Jupyter/IPython notebooks on Python 3.14+, use `await` directly for async methods. Synchronous wrappers relying on `nest_asyncio` may fail with `RuntimeError`. Migrate to explicit `await` calls for asynchronous operations.
gotcha Using `asyncio.Lock` (or other synchronization primitives like `Semaphore`, `Event`) in a global scope and then repeatedly calling `asyncio.run()` can lead to `RuntimeError`. This happens because `asyncio.run()` creates a new event loop each time, and the global lock object might retain a stale reference to a previously closed loop. ↓
fix Initialize `asyncio` synchronization primitives within the scope of your `asyncio.run()` execution or pass them explicitly between coroutines to ensure they are associated with the correct, currently active event loop.
Install compatibility verified last tested: 2026-05-12
python os / libc status wheel install import disk
3.10 alpine (musl) wheel - 0.08s 17.8M
3.10 alpine (musl) - - 0.08s 17.8M
3.10 slim (glibc) wheel 1.4s 0.06s 18M
3.10 slim (glibc) - - 0.05s 18M
3.11 alpine (musl) wheel - 0.16s 19.6M
3.11 alpine (musl) - - 0.17s 19.6M
3.11 slim (glibc) wheel 1.7s 0.13s 20M
3.11 slim (glibc) - - 0.12s 20M
3.12 alpine (musl) wheel - 0.35s 11.5M
3.12 alpine (musl) - - 0.37s 11.5M
3.12 slim (glibc) wheel 1.7s 0.33s 12M
3.12 slim (glibc) - - 0.31s 12M
3.13 alpine (musl) wheel - 0.37s 11.2M
3.13 alpine (musl) - - 0.37s 11.1M
3.13 slim (glibc) wheel 1.5s 0.34s 12M
3.13 slim (glibc) - - 0.32s 12M
3.9 alpine (musl) wheel - 0.07s 17.3M
3.9 alpine (musl) - - 0.08s 17.3M
3.9 slim (glibc) wheel 1.7s 0.06s 18M
3.9 slim (glibc) - - 0.06s 18M
Imports
- asyncio
import asyncio
Quickstart last tested: 2026-04-24
import asyncio
import time
async def say_after(delay, what):
await asyncio.sleep(delay)
print(what)
async def main():
print(f"started at {time.strftime('%X')}")
await say_after(1, 'hello')
await say_after(2, 'world')
print(f"finished at {time.strftime('%X')}")
if __name__ == "__main__":
# The recommended way to run the top-level async function.
asyncio.run(main())