asyncio-loop-local
asyncio-loop-local storage, singletons and deferred aexit's. Init that pool once and reuse it!
why have loop-local things
Suppose you have some async context manager, like aiohttp.ClientSession:
async with aiohttp.ClientSession() as session:
async with session.get('http://httpbin.org/get') as resp:
print(await resp.text())
But the docs tell you: "don't create a session per request". So, you need to reuse it somehow, and this means you need to init it somewhere and then either pass it around all the code that might need it, or... use global variables? There must be a better way.
sticky_singleton_acm
The all-in-one solution to this is:
_ClientSession = asyncio_loop_local.sticky_singleton_acm(ClientSession)
...
async _ClientSession() as session:
async with session.get('http://httpbin.org/get') as resp:
print(await resp.text())
The wrapper gives you
- the same
ClientSessionfor every combination of parameters passed to it (singleton) - that doesn't
__aexit__when the block is over, only when the async event loop is closed (sticky ACM)
enter_once + singleton
Those willing to save up a level of indentation
(after all, de-denting is a no-op as __aexit__'ing effect is deferred anyway)
might be interested in
combining two simpler primitives to the same effect:
_ClientSession = asyncio_loop_local.singleton(ClientSession)
...
session = await asyncio_loop_local.enter_once(_ClientSession())
async with session.get('http://httpbin.org/get') as resp:
print(await resp.text())
singleton
Decorate your callable that generates something, and the returned value will be cached per async loop (and per passed parameters).
_ClientSession = asyncio_loop_local.singleton(ClientSession)
_ClientSession() is _ClientSession() # as long you're in the same event loop
enter_once
Invoke __anter__ of an asynchronous context manager now,
defer __aexit__ to the end of the event loop.
Repeated attempts to enter_once on the same object will do nothing.
session = await asyncio_loop_local.enter_once(ClientSession())
...
# __aexit__ will be executed at the end of the event loop
sticky_acm
Wrap an asynchronous context manager.
__anter__ just proxies the original context manager's __aenter__,
__aexit__ does nothing and is deferred to end of the event loop.
It's like enter_once, but in a form to use with async with.
cs = asyncio_loop_local.sticky_acm(ClientSession())
async with cs: # __aenter__'s
...
# __aexit__ will be executed at the end of the event loop
enter
Invoke __anter__ of an asynchronous context manager now,
defer __aexit__ to the end of the event loop.
session = await asyncio_loop_local.enter_once(ClientSession())
...
# __aexit__ will be executed at the end of the event loop
storage
Async-loop-local storage. Like thread-local, but loop-local. All the hacks above are built up on it.
alls = asyncio_loop_local._storage.storage() # gives a loop-associated dict
alls['purpose'] = ('whatever', {'you': 'want'})
If you wanna use locking, consider this:
class LockingDict(asyncio.Lock, dict): pass
alls['careful'] = LockingDict()
with alls['careful'] as d:
d['a'] = 'b'
_atexit
There's also an async-loop-local atexit hook implementation. It's private so far until some interest is expressed.
Metadata
Release files for asyncio-loop-local 0.0.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| asyncio_loop_local-0.0.4.tar.gz | 47.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| asyncio_loop_local-0.0.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 80.1 kB
Release files / asyncio_loop_local-0.0.4.tar.gz
| Download URL | asyncio_loop_local-0.0.4.tar.gz |
|---|---|
| Size | 47.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d4cde7234066a1adc3c27c6dd6a8dc2d87173de3702f9ae0948e44b8a46edde6
|
|
BLAKE2b-256 checksum How to use checksums |
842c6b55ad2e0356598f35f296533b7f1e14426403c8a41525b438b0d96110f2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.1 CPython/3.11.6
|
Release files / asyncio_loop_local-0.0.4-py3-none-any.whl
| Download URL | asyncio_loop_local-0.0.4-py3-none-any.whl |
|---|---|
| Size | 33.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b3fc14b40349190b3488ed62a0e2f3647c79c3b5ab6b652bcb3a2e139d2192e2
|
|
BLAKE2b-256 checksum How to use checksums |
7405a59804e2e68ae1316e3d577738d1cc045936e9a5d03f3e42a9c0c9485625
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.1 CPython/3.11.6
|
Security for asyncio-loop-local 0.0.4
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.