Documentation for pulsar 0.9.2. For development docs, go here.
There are three, closely related, ways to create asynchronous components in pulsar:
Directly create a of Future
:
import asyncio
o = asyncio.Future()
or, equivalently:
import pulsar
o = pulsar.Future()
A coroutine, a generator which consumes values. For example:
from pulsar import coroutine_return
def my_async_generator(...):
yield something_but_dont_care_what_it_returns()
...
bla = yield something_and_care_what_it_returns()
result = yield do_something(bla)
coroutine_return(result)
a coroutine is obtained by calling the generator function:
o = my_async_generator()
Note that o
is coroutine which has not yet started.
An asyncio.Task
, is a component which has been added to
pulsar asynchronous engine. It is created via the async()
function
when applied to a generator function or, equivalently, by the
in_loop()
and task()
decorators:
from pulsar import async
def my_async_generator1(...):
yield something_but_dont_care_what_it_returns()
...
bla = yield something_and_care_what_it_returns()
yield do_something(bla)
task = async(my_async_generator2())
A Task
is a subclass of Future
and
therefore it has the same API, for example, you can add callbacks to a task:
task.add_done_callback(...)
As mentioned above, a coroutine is a generator which consumes values. A pulsar
coroutine can consume synchronous values as well as Future
and other coroutines.
Let’s consider the following code:
d = Future()
def do_something(...):
yield something_but_dont_care_what_it_returns()
...
bla = yield something_and_care_what_it_returns()
result = yield do_something(bla)
coroutine_return(result)
def my_async_generator():
result = yield d
yield do_something(result)
Then we create a coroutine by calling the my_async_generator
generator
function:
o = my_async_generator()
o
is has not yet started. To use it, it must be added to pulsar
asynchronous engine via the async()
function:
task = async(o)
task is a Task
instance.
Coroutines can return values via the coroutine_return()
function.
Otherwise they always return None
(unless exceptions occur).
A Task
is a specialised Future
which consumes
coroutines.
A coroutine is transformed into a Task
via the async()
function or the in_loop()
and
task()
decorators.
A task consumes a coroutine until the coroutine yield an asynchronous component
not yet done. When this appends, the task pauses and returns the control of execution.
Before it returns, it adds a callback
to the Future
on which the coroutine is blocked to resume the coroutine once the future
is called.
A task in this state is said to be suspended.
When dealing with several asynchronous components in a collection such as
a list, tuple, set or even a dictionary (values only, keys must be synchronous
python types), one can use the multi_async()
function to create
an asynchronous component which will be ready once all the components
are ready.