{"id":6962,"library":"aiocontextvars","title":"aiocontextvars","description":"aiocontextvars provides asyncio support for the PEP-567 contextvars backport, effectively offering 'task local' storage similar to 'threading.local' but scoped to asyncio tasks. It is primarily relevant for Python versions 3.5 and 3.6, as Python 3.7 and later include native `contextvars` support. The project is currently at version 0.2.2 and is explicitly marked for deprecation once native asyncio contextvars support is fully stable in older backports.","status":"deprecated","version":"0.2.2","language":"en","source_language":"en","source_url":"https://github.com/fantix/aiocontextvars","tags":["asyncio","contextvars","concurrency","python3.5","python3.6","backport"],"install":[{"cmd":"pip install aiocontextvars","lang":"bash","label":"Install aiocontextvars"}],"dependencies":[{"reason":"Required for Python 3.5/3.6 as a PEP-567 backport dependency. Not needed for Python 3.7+ as contextvars is built-in.","package":"contextvars","optional":false}],"imports":[{"symbol":"ContextVar","correct":"from aiocontextvars import ContextVar"},{"symbol":"copy_context","correct":"from aiocontextvars import copy_context"}],"quickstart":{"code":"import asyncio\nfrom aiocontextvars import ContextVar\n\n# Define a ContextVar\nmy_variable = ContextVar('my_variable', default='default_value')\n\nasync def child_task(task_id):\n    current_val = my_variable.get()\n    print(f\"Task {task_id}: Initial value in child: {current_val}\")\n    my_variable.set(f\"value_from_task_{task_id}\")\n    print(f\"Task {task_id}: New value set in child: {my_variable.get()}\")\n    await asyncio.sleep(0.1)\n\nasync def main():\n    print(f\"Main: Initial value: {my_variable.get()}\")\n    token = my_variable.set(\"main_context_value\")\n    print(f\"Main: Value after set: {my_variable.get()}\")\n\n    # Spawning child tasks - they inherit the context at creation\n    tasks = [\n        asyncio.create_task(child_task(1)),\n        asyncio.create_task(child_task(2))\n    ]\n    await asyncio.gather(*tasks)\n\n    print(f\"Main: Value after children complete: {my_variable.get()}\")\n    my_variable.reset(token)\n    print(f\"Main: Value after reset: {my_variable.get()}\")\n\nif __name__ == '__main__':\n    # IMPORTANT: aiocontextvars must be imported BEFORE creating event loops.\n    # For Python 3.5/3.6, ensure aiocontextvars is imported early in your application.\n    asyncio.run(main())\n","lang":"python","description":"This quickstart demonstrates defining and using a `ContextVar` within an asyncio application. It shows how values set in a parent task are inherited by child tasks upon creation, and how to set and retrieve values using `ContextVar.set()` and `ContextVar.get()`. `ContextVar.reset()` is used with the token returned by `set()` to restore previous context."},"warnings":[{"fix":"Upgrade to Python 3.7+ and use `import contextvars` directly. For Python 3.5/3.6, continue using `aiocontextvars` but be aware of its maintenance status.","message":"This package is explicitly marked for deprecation. For Python 3.7+ environments, `contextvars` is built into the standard library and should be used directly. This library's primary purpose is a backport for Python 3.5/3.6.","severity":"deprecated","affected_versions":"All versions"},{"fix":"Update code to use `ContextVar.set()` with `token = var.set(value)` and later `var.reset(token)`. Remove calls to deprecated `delete()`, `enable_inherit()`, and `disable_inherit()`.","message":"Version 0.2.0 introduced significant breaking changes. `ContextVar.delete()` was removed, `enable_inherit()` and `disable_inherit()` functions were removed (inheritance is always enabled), and `ContextVar.set()` now returns a `Token` object which must be used with the newly added `ContextVar.reset(token)` to restore the previous value.","severity":"breaking","affected_versions":"<0.2.0"},{"fix":"Ensure `import aiocontextvars` is one of the first lines of code executed in your application's entry point.","message":"For correct behavior (especially patching `asyncio.get_event_loop` and `loop.create_task`), `aiocontextvars` MUST be imported at the very beginning of your application, before any asyncio event loops are created. Loops created before the import will not be patched.","severity":"gotcha","affected_versions":"All versions on Python 3.5/3.6"},{"fix":"Design your application with this snapshot behavior in mind. If you need dynamic updates across tasks, consider passing data explicitly or using other synchronization primitives.","message":"Contexts are copied when a new task is created (e.g., via `asyncio.create_task` or `asyncio.gather`). Changes made to `ContextVar` values in a parent task *after* a child task has been spawned will NOT be visible to that already-running child task, as it operates on a snapshot of the context at its creation time.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Wrap your callable with `copy_context().run`. Example: `loop.call_soon(copy_context().run, my_method)`.","message":"When using `loop.call_soon()` (or similar low-level scheduling functions) in Python 3.5/3.6 and expecting context inheritance, you must explicitly pass the context. The standard `call_soon` in these versions does not automatically copy the context.","severity":"gotcha","affected_versions":"All versions on Python 3.5/3.6"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Ensure `var.set(value)` is called at least once in the current context (or a parent context if inherited) before calling `var.get()`. You can also provide a default value when initializing the `ContextVar`: `my_variable = ContextVar('my_variable', default='initial_value')`.","cause":"Attempting to retrieve the value of a `ContextVar` using `var.get()` before a value has been set in the current execution context.","error":"LookupError: 'ContextVar' has no value in this context"},{"fix":"Replace `var.delete()` with `var.reset(token)` where `token` was the result of the `var.set()` call you wish to revert. If no token is available, you cannot 'delete' a value, only reset to a prior state.","cause":"Attempting to use the `delete()` method on a `ContextVar` object, which was removed in version 0.2.0.","error":"AttributeError: 'ContextVar' object has no attribute 'delete'"},{"fix":"Always use public `asyncio` APIs (e.g., `asyncio.run()`, `asyncio.create_task()`, `asyncio.get_event_loop()`) and ensure `aiocontextvars` is imported at startup. If using `uvloop`, consider if `aiocontextvars` is the right solution, as `uvloop` might need specific integration not provided by this library.","cause":"`aiocontextvars` patches `asyncio.get_event_loop` and `loop.create_task`. Custom event loop implementations (like `uvloop`) or directly creating `asyncio.Task` instances via private APIs might bypass these patches, leading to incorrect context propagation.","error":"Context not propagating correctly with uvloop or custom task factories."}]}