This is a small package which provides tools to run async
functions and
generators without an asyncio
event loop.
The coroutines
module provides functions such as coroutines.run()
,
coroutines.gather()
, and coroutines.sleep()
that work just like their
asyncio
counterparts, but without scheduling any tasks in an external event
loop. For example, the following code was adapted from the asyncio
documentation:
import coroutines
async def factorial(name, number):
f = 1
for i in range(2, number + 1):
print(f"Task {name}: Compute factorial({number}), currently i={i}...")
await coroutines.sleep() # CHANGED: no argument
f *= i
print(f"Task {name}: factorial({number}) = {f}")
return f
async def main():
# Schedule three calls *concurrently*:
L = await coroutines.gather(
factorial("A", 2),
factorial("B", 3),
factorial("C", 4),
)
print(L)
coroutines.run(main())
# Expected output:
#
# Task A: Compute factorial(2), currently i=2...
# Task B: Compute factorial(3), currently i=2...
# Task C: Compute factorial(4), currently i=2...
# Task A: factorial(2) = 2
# Task B: Compute factorial(3), currently i=3...
# Task C: Compute factorial(4), currently i=3...
# Task B: factorial(3) = 6
# Task C: Compute factorial(4), currently i=4...
# Task C: factorial(4) = 24
# [2, 6, 24]
The example produces the same result as the asyncio
code by simply calling,
suspending, and resuming the coroutines until they are completed. Practically,
the only difference between the coroutines
and asyncio
examples is that
coroutines.sleep()
does not take an argument. Because there is no external
event loop, a call to coroutines.sleep()
cannot suspend the current chain of
coroutines for a fixed amount of time, but only until it is resumed at the next
iteration.
coroutines.run(coro) #
Run a coroutine from synchronous code.
awaitable coroutines.sleep() #
Suspend the current chain of coroutines, allowing another coroutine to run concurrently.
awaitable coroutines.gather(*aws) #
Run the given awaitables aws concurrently.
Returns a coroutine that loops over aws, resuming each awaitable in
turn until it is suspended again or finished. Execution is suspended
after each pass over aws, so that other coroutines can run while the
result of gather()
is being awaited.
The result of awaiting gather()
is the aggregate list of awaited results
from aws in the same order.
The coroutines
module contains a number of helper functions that turn
regular objects into awaitable variants of themselves.
awaitable coroutines.awaitable(obj=None) #
Create an awaitable variant of obj. Returns a coroutine that awaits
coroutines.sleep()
before returning obj.
awaitable coroutines.aiterable(iterable) #
Create an awaitable variant of an iterable. Returns an asynchronous generator
that awaits coroutines.sleep()
before each item in iterable.
awaitable coroutines.arange(stop) # awaitable coroutines.arange(start, stop[, step])
Create an awaitable variant of range()
. Returns an asynchronous generator
that awaits coroutines.sleep()
before each number.