{
    "slug": "py_async",
    "term": "Python async/await & asyncio",
    "category": "python",
    "difficulty": "intermediate",
    "short": "Python's native async framework — coroutines, event loop, and asyncio — for concurrent I/O without threads.",
    "long": "Python's asyncio provides a single-threaded event loop similar to Node.js. async def functions are coroutines — they don't run until awaited or scheduled. await suspends the coroutine until the awaited coroutine/task finishes. asyncio.gather(*coros) runs coroutines concurrently. asyncio.run(main()) starts the event loop. For CPU-bound work, asyncio doesn't help — use multiprocessing or ThreadPoolExecutor (loop.run_in_executor). Key difference from threading: no GIL contention, but no true parallelism either — only concurrency for I/O. Libraries: httpx (async HTTP), asyncpg (async PostgreSQL), aiofiles (async file I/O), FastAPI (async web framework). Comparable to PHP's Fibers + Revolt, but asyncio is a mature standard library with rich ecosystem support.",
    "aliases": [
        "Python asyncio",
        "async await Python",
        "coroutines Python"
    ],
    "tags": [
        "python",
        "async",
        "concurrency"
    ],
    "misconception": "Python async/await provides true parallelism. Python's asyncio is single-threaded cooperative concurrency — one coroutine runs at a time, yielding control at await points. For CPU-bound parallelism, use multiprocessing; for I/O-bound concurrency, asyncio is ideal.",
    "why_it_matters": "Python's asyncio enables concurrent I/O-bound operations in a single thread — async/await syntax makes concurrent HTTP calls and database queries readable without threads or callbacks.",
    "common_mistakes": [
        "Using blocking I/O inside async functions — blocks the entire event loop.",
        "Not awaiting coroutines — calling an async function without await returns a coroutine object, not the result.",
        "Using asyncio.run() inside an already-running event loop — raises RuntimeError.",
        "CPU-bound work in async functions — use ProcessPoolExecutor, not asyncio, for CPU-heavy tasks."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "py_generators",
        "js_async_await",
        "fibers_revolt"
    ],
    "prerequisites": [
        "py_generators",
        "js_event_loop",
        "coroutines"
    ],
    "refs": [
        "https://docs.python.org/3/library/asyncio.html"
    ],
    "bad_code": "# Blocking call inside async — freezes event loop:\nasync def fetch_data():\n    time.sleep(2)  # Blocks! Use: await asyncio.sleep(2)\n    data = requests.get(url)  # Blocks! Use: await aiohttp session\n    return data",
    "good_code": "import asyncio\nimport aiohttp\n\n# Async function — returns a coroutine\nasync def fetch_user(session: aiohttp.ClientSession, user_id: int) -> dict:\n    async with session.get(f'https://api.example.com/users/{user_id}') as resp:\n        return await resp.json()\n\n# Fetch multiple users concurrently\nasync def fetch_all_users(user_ids: list[int]) -> list[dict]:\n    async with aiohttp.ClientSession() as session:\n        tasks = [fetch_user(session, uid) for uid in user_ids]\n        return await asyncio.gather(*tasks)  # run concurrently\n\n# Run:\nusers = asyncio.run(fetch_all_users([1, 2, 3, 4, 5]))\n\n# async with — async context manager\n# async for  — async iteration (e.g. streaming responses)\nasync def stream_lines(url: str):\n    async with aiohttp.ClientSession() as session:\n        async with session.get(url) as resp:\n            async for line in resp.content:\n                yield line.decode('utf-8').strip()",
    "quick_fix": "Use asyncio.gather() for concurrent I/O operations and async with for context managers in async code — synchronous blocking calls inside async functions block the entire event loop",
    "severity": "medium",
    "effort": "high",
    "created": "2026-03-15",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/py_async",
        "html_url": "https://codeclaritylab.com/glossary/py_async",
        "json_url": "https://codeclaritylab.com/glossary/py_async.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Python async/await & asyncio](https://codeclaritylab.com/glossary/py_async) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/py_async"
            }
        }
    }
}