Skip to main content

Idiomatic asyncio utilities

Project description

aiotools

PyPI release version Supported Python versions Build Status Code Coverage

Idiomatic asyncio utilties

NOTE: This project is under early stage of developement. The public APIs may break version by version.

Modules

Examples

Async Context Manager

This is an asynchronous version of contextlib.contextmanager to make it easier to write asynchronous context managers without creating boilerplate classes.

import asyncio
import aiotools

@aiotools.actxmgr
async def mygen(a):
   await asyncio.sleep(1)
   yield a + 1
   await asyncio.sleep(1)

async def somewhere():
   async with mygen(1) as b:
       assert b == 2

Note that you need to wrap yield with a try-finally block to ensure resource releases (e.g., locks), even in the case when an exception is ocurred inside the async-with block.

import asyncio
import aiotools

lock = asyncio.Lock()

@aiotools.actxmgr
async def mygen(a):
   await lock.acquire()
   try:
       yield a + 1
   finally:
       lock.release()

async def somewhere():
   try:
       async with mygen(1) as b:
           raise RuntimeError('oops')
   except RuntimeError:
       print('caught!')  # you can catch exceptions here.

You can also create a group of async context managers, which are entered/exited all at once using asyncio.gather().

import asyncio
import aiotools

@aiotools.actxmgr
async def mygen(a):
   yield a + 10

async def somewhere():
   ctxgrp = aiotools.actxgroup(mygen(i) for i in range(10))
   async with ctxgrp as values:
       assert len(values) == 10
       for i in range(10):
           assert values[i] == i + 10

Async Server

This implements a common pattern to launch asyncio-based server daemons.

import asyncio
import aiotools

async def echo(reader, writer):
   data = await reader.read(100)
   writer.write(data)
   await writer.drain()
   writer.close()

@aiotools.server
async def myworker(loop, pidx, args):
   server = await asyncio.start_server(echo, '0.0.0.0', 8888,
       reuse_port=True, loop=loop)
   print(f'[{pidx}] started')
   yield  # wait until terminated
   server.close()
   await server.wait_closed()
   print(f'[{pidx}] terminated')

if __name__ == '__main__':
   # Run the above server using 4 worker processes.
   aiotools.start_server(myworker, num_workers=4)

It handles SIGINT/SIGTERM signals automatically to stop the server, as well as lifecycle management of event loops running on multiple processes.

Async Timer

import aiotools

i = 0

async def mytick(interval):
   print(i)
   i += 1

async def somewhere():
   t = aiotools.create_timer(mytick, 1.0)
   ...
   t.cancel()
   await t

t is an asyncio.Task object. To stop the timer, call t.cancel(); await t. Please don't forget await-ing t because it requires extra steps to cancel and await all pending tasks. To make your timer function to be cancellable, add a try-except clause catching asyncio.CancelledError since we use it as a termination signal.

You may add TimerDelayPolicy argument to control the behavior when the timer-fired task takes longer than the timer interval. DEFAULT is to accumulate them and cancel all the remainings at once when the timer is cancelled. CANCEL is to cancel any pending previously fired tasks on every interval.

import asyncio
import aiotools

async def mytick(interval):
   await asyncio.sleep(100)  # cancelled on every next interval.

async def somewhere():
   t = aiotools.create_timer(mytick, 1.0, aiotools.TimerDelayPolicy.CANCEL)
   ...
   t.cancel()
   await t

Changelog

0.8.1 (2019-02-24)

  • server: Fix yields of the received stop signal in main/worker context managers when using threaded workers.

0.8.0 (2018-11-18)

  • server: Updated stop signal handling and now user-defined worker/main context managers have a way to distinguish the stop signal received. See the updated docs for more details.

0.7.3 (2018-10-16)

  • This ia a technical release to fix a test case preventing the automated CI release procedure.

0.7.2 (2018-10-16)

  • Improve support for Python 3.6/3.7 using a small compatibility module against asyncio.

  • func: Add expire_after option to lru_cache() function.

0.7.1 (2018-08-24)

  • Minor updates to the documentation

0.7.0 (2018-08-24)

  • Add support for Python 3.7

  • context: Updated to work like Python 3.7

  • context: Deprecated AsyncContextDecorator stuffs in Python 3.7+

  • context: Added an alias to contextlib.AsyncExitStack in the standard library.

0.6.0 (2018-04-10)

  • Introduce a new module aiotools.iter with aiter() function which corresponds to an async version of the builtin iter().

0.5.4 (2018-02-01)

  • server: Remove use of unncessary setpgrp syscall, which is also blocked by Docker's default seccomp profile!

0.5.3 (2018-01-12)

  • server: Ooops! (a finally block should have been an else block)

0.5.2 (2018-01-12)

  • server: Improve inner beauty (code readability)

  • server: Improve reliability and portability of worker-to-main interrupts

0.5.1 (2018-01-11)

  • server: Fix a race condition related to handling of worker initialization errors with multiple workers

0.5.0 (2017-11-08)

  • func: Add lru_cache() which is a coroutine version of functools.lru_cache()

0.4.5 (2017-10-14)

  • server: Fix a race condition related to signal handling in the multiprocessing module during termination

  • server: Improve error handling during initialization of workers (automatic shutdown of other workers and the main loop after logging the exception)

0.4.4 (2017-09-12)

  • Add a new module aiotools.func with apartial() function which is an async version of functools.partial() in the standard library

0.4.3 (2017-08-06)

  • Add aclosing() context manager like closing() in the standard library

  • Speed up Travis CI builds for packaging

  • Now provide README in rst as well as CHANGES (this file)

0.4.2 (2017-08-01)

  • server: Fix spawning subprocesses in child workers

  • Add support for uvloop

0.4.0 (2017-08-01)

  • Add use_threading argument to

  • Add initial documentation (which currently not served on readthedocs.io due to Python version problem)

0.3.2 (2017-07-31)

  • Add extra_procs argument to start_server() function

  • Add socket and ZeroMQ server examples

  • Improve CI configs

0.3.1 (2017-07-26)

  • Improve CI scripts

  • Adopt editorconfig

0.3.0 (2017-04-26)

  • Add start_server() function using multiprocessing with automatic children lifecycle management

  • Clarify the semantics of AsyncContextGroup using asyncio.gather() with return_exceptions=True

0.2.0 (2017-04-20)

  • Add abstract types for AsyncContextManager

  • Rename AsyncGenContextManager to AsyncContextManager

  • Add AsyncContextGroup

0.1.1 (2017-04-14)

  • Initial release

Project details


Release history Release notifications | RSS feed

Download files

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

Source Distribution

aiotools-0.8.1.tar.gz (17.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aiotools-0.8.1-py3-none-any.whl (16.9 kB view details)

Uploaded Python 3

File details

Details for the file aiotools-0.8.1.tar.gz.

File metadata

  • Download URL: aiotools-0.8.1.tar.gz
  • Upload date:
  • Size: 17.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.20.0 setuptools/40.8.0 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.7.1

File hashes

Hashes for aiotools-0.8.1.tar.gz
Algorithm Hash digest
SHA256 80f5c2ea26eb169cfcc1b11bb437b5d120e259b7470186d7afac51716fbf08a5
MD5 f9f58d72feee29a6d4a15b424ba29a9c
BLAKE2b-256 3e54c2a7245aff90efe27eab4ab2f6ead71dfc0d381674779a6211b0287d21c0

See more details on using hashes here.

File details

Details for the file aiotools-0.8.1-py3-none-any.whl.

File metadata

  • Download URL: aiotools-0.8.1-py3-none-any.whl
  • Upload date:
  • Size: 16.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.20.0 setuptools/40.8.0 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.7.1

File hashes

Hashes for aiotools-0.8.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9cfeac44cb98d6353c96a0d2577a9aefb7ec2272ec20f2bba1a963eb1fa2172b
MD5 c6f0f2b1d710daba85b16d1617ccce32
BLAKE2b-256 d1ccad6d24e02c8a3c9101b51ea6764114d7600bba2aba37015e8a4bb936ad7e

See more details on using hashes here.

Supported by

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