Asyncio

asyncio is a library to write concurrent code using the async / await syntax. asyncio is used as a foundation for multiple Python asynchronous frameworks that provide high-performance network and web-servers, database connection libraries, distributed task queues, etc.

Asyncio & Cowait

Cowait uses asyncio for running concurrent tasks. asyncio has a very simple interface to write sequential (blocking) and parallel (non-blocking) operations.

Remember that in Cowait, a call to another task will be intercepted by the Cowait runtime and executed in a separate container — potentially on a different machine.

Before we get into running concurrent tasks, let's look at a very simple example that uses asyncio to sleep for 5 seconds.

sleep.py
import asyncio
from cowait import task

@task
async def Sleep(duration: int = 5):
    for i in range(duration):
      await asyncio.sleep(1) # blocking
      print("slept", i + 1)

    return {
        "duration": duration,
    }

Cowait tasks are defined with the async keyword. This allows us to wait for other tasks in an asynchronous fashion, or to use basic features from asyncio, like sleep(n). Run the above example:

cowait run sleep

Parallel Tasks

One of the core features of Cowait is its simple interface to parallelize work on multiple containers. Let's add a new task that spawns multiple Sleep tasks in parallel:

parallel.py
import asyncio
from cowait import task, join
from sleep import Sleep

@task
async def Parallel():
    tasks = [Sleep(duration=5), Sleep(duration=5)]

    result = await join(tasks)

    return result

Here, Cowait provides a utility method join to wait for a list of tasks. It is a very simple wrapper for asyncio.gather(). Run your new parallel task:

cowait run parallel

The parallel task creates two child containers (so 3 in total), that each sleeps for 5 seconds (in parallel). Here's an illustration of the above example:

Parallel Docker Illustration

You will note that the program doesn't run for precisely 5 seconds, and that the Sleep containers may start / exit at different times (however parallel will block until both are done). This is because there is some overhead in the underlying docker engine to create and spawn new containers for the tasks.

Found incorrect information, typos or have other suggestions to this documentation page?

Edit on Github