Skip to main content

PEP-550 polyfill, execution context for asyncio.

Project description

aiocontextvars

https://img.shields.io/pypi/v/aiocontextvars.svg https://img.shields.io/travis/fantix/aiocontextvars.svg

IMPORTANT: This package will be deprecated after contextvars asyncio backport is fixed.

This library is a compatibility wrapper of contextvars library introduced in Python 3.7, or its backport for Python 3.5 and 3.6. It offers the “thread local” for Python asyncio, also known as “task local”.

Please read more in Python 3.7 [contextvars documentation]( https://docs.python.org/3/library/contextvars.html).

import asyncio
from aiocontextvars import ContextVar

var = ContextVar('my_variable')

async def main():
    var.set('main')
    await sub()
    assert var.get() == 'sub'

async def sub():
    assert var.get() == 'main'
    var.set('sub')
    assert var.get() == 'sub'

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

In above example, value main was stored in var, and the following code could then retrieve the value wherever var is available, without having to pass this value around as parameter, e.g. in sub. In the mean time, sub could also mutate the value, while being visible to its caller.

Different than a global variable and similar to thread local, a ContextVar keeps the different values set in different tasks, without messing up:

import asyncio
from aiocontextvars import ContextVar

var = ContextVar('my_variable')

async def main(count):
    var.set(count)
    await asyncio.sleep(1)  # make sure all counts are set before assertion
    await sub(count)
    assert var.get() == count + 1

async def sub(count):
    assert var.get() == count
    var.set(count + 1)
    assert var.get() == count + 1

loop = asyncio.get_event_loop()

tasks = []
for i in range(8):
    tasks.append(loop.create_task(main(i)))

loop.run_until_complete(asyncio.gather(*tasks))

With such, it is usually used to store non-global but shared states, e.g. requests or database connections.

Compatibility

In Python 3.7 this package is 100% contextvars.

In Python 3.5 and 3.6, this package added asyncio support to the PEP-567 backport package also named contextvars, in a very different way than Python 3.7 contextvars implementation:

  1. call_soon() and family methods.

Python 3.7 added keyword argument context to call_soon() and its family methods. By default those methods will copy (inherit) the current context and run the given method in that context. But aiocontextvars won’t touch the loop, so in order to achieve the same effect, you’ll need to:

loop.call_soon(copy_context().run, my_meth)
  1. Task local.

Python 3.7 used above keyword argument context in Task to make sure that each step of a coroutine is ran in the same context inherited at the time its driving task was created. Meanwhile, aiocontextvars uses Task.current_task() to achieve similar effect: it hacks asyncio and attaches a copied context to the task on its creation, and replaces thread local with current task instance to share the context. This behaves identically to Python 3.7 in most times. What you need to do is to import aiocontextvars before creating loops.

  1. Custom tasks and loops.

Because above hack is done by replacing asyncio.get_event_loop and loop.create_task, therefore tasks and loops created by custom/private API won’t behave correctly as expected, e.g. uvloop.new_event_loop() or asyncio.Task(). Also, event loops created before importing aiocontextvars are not patched either. So over all, you should import aiocontextvars at the beginning before creating event loops, and always use asyncio.* to operate loops/policies, and public asyncio API to create tasks.

Credits

Fantix King is the author and maintainer of this library. This library is open source software under BSD license.

History

0.2.0 (2018-09-09)

This is a breaking change. Most implementation is replaced with contextvars. In Python 3.5 and 3.6, aiocontextvars depends on contextvars the PEP-567 backport in PyPI, and patches it to partially support asyncio; in Python 3.7 aiocontextvars is only a delegate to the built-in contextvars library.

  • Modified ContextVar.set() to return a token.

  • Added ContextVar.reset(token).

  • Removed ContextVar.delete().

  • Removed enable_inherit() and disable_inherit(), inherit is always enabled.

  • Added copy_context() and Context.run().

  • Removed Context.current() and Context.inherited.

  • Fixed issue that set_event_loop(None) fails (contributed by J.J. Jackson in #10 #11)

0.1.2 (2018-04-04)

  • Supported Python 3.5.

0.1.1 (2017-12-03)

  • Fixed setup.py

0.1.0 (2017-12-03)

  • First release on PyPI.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aiocontextvars-0.2.0.tar.gz (16.5 kB view details)

Uploaded Source

Built Distribution

aiocontextvars-0.2.0-py2.py3-none-any.whl (4.1 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file aiocontextvars-0.2.0.tar.gz.

File metadata

  • Download URL: aiocontextvars-0.2.0.tar.gz
  • Upload date:
  • Size: 16.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.11.0 pkginfo/1.4.2 requests/2.19.1 setuptools/40.2.0 requests-toolbelt/0.8.0 tqdm/4.25.0 CPython/3.6.3

File hashes

Hashes for aiocontextvars-0.2.0.tar.gz
Algorithm Hash digest
SHA256 eaf193d9ffc5b1942d612ae28d90f1ef5eb59981e41fe38f3863b769eceb301a
MD5 40cae13e3e5bd162e4f922b32127fcc2
BLAKE2b-256 b1d1c6313174b1cbcf3bf8f7bdb3175e2ef9b0d2d8f70544361403ff5d101722

See more details on using hashes here.

Provenance

File details

Details for the file aiocontextvars-0.2.0-py2.py3-none-any.whl.

File metadata

  • Download URL: aiocontextvars-0.2.0-py2.py3-none-any.whl
  • Upload date:
  • Size: 4.1 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.11.0 pkginfo/1.4.2 requests/2.19.1 setuptools/40.2.0 requests-toolbelt/0.8.0 tqdm/4.25.0 CPython/3.6.3

File hashes

Hashes for aiocontextvars-0.2.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 530f3054f65c2d5f0cf25700bac33a8c0254da519320a334205e8ec0cdbc6adb
MD5 fbf9065ae8eb9844ffb2e8625df65985
BLAKE2b-256 c5abfb86407b574b7bb2e67600c9798883e8d7dce46d4023c002f864be0e4b2e

See more details on using hashes here.

Provenance

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page