score.asyncio¶
A module that manages a configured asyncio.AbstractEventLoop
.
Quickstart¶
If you have no preferences about the library to use, initializing the module with its defaults is sufficient:
[score]
modules =
score.asyncio
You can now start/stop the loop from anywhere by grabbing a loop token:
token = configured_asyncio.start_loop()
# ... the loop is guaranteed to be running now ...
token.release()
# if this was the last token, the loop will stop.
# otherwise it will keep running until all
# tokens have been released.
Configuration¶
-
score.asyncio.
init
(confdict)[source]¶ Initializes this module according to the SCORE module initialization guidelines with the following configuration keys:
- backend “builtin”
- The library to use for creating the event loop. Current valid values
are
uvloop
andbuiltin
. - use_global_loop False
- Whether the global loop object should be used. The “global” loop is the
one returned by
asyncio.get_event_loop()
. - stop_timeout None
Defines how long the module will wait for all tasks running in the loop to finish when stopping the loop. The value will be interpreted through a call to
score.init.parse_time_interval()
.The default value None indicates that the module will wait indefinitely. If you want to the loop to terminate immediately, without waiting for tasks at all, you must pass “0”.
Details¶
Starting the Loop¶
Since the sole purpose of this module is to provide a common
asyncio.AbstractEventLoop
to different, potentially unrelated SCORE
modules, this module must decide when the loop must be started and when it can
be stopped.
This is why any module using this one must indicate its intention to use the
loop by calling the configured module’s start_loop
method.
The configured module will make sure that the loop is running after the first
call to its start_loop
method and
will stop the loop automatically when all loop tokens have
been released.
The following is an excerp from one of the unit tests that demonstrates this behavior:
assert not configured_asyncio.loop.is_running()
for _ in range(10):
token = configured_asyncio.start_loop()
assert configured_asyncio.loop.is_running()
tokens.append(token)
for token in tokens:
assert configured_asyncio.loop.is_running()
token.release()
assert not configured_asyncio.loop.is_running()
There are three different, identical ways to stop a running loop:
- Invoking the token’s
release
method, - passing the token to the configured module’s
release_loop
method and - using the token as a context manager (i.e. in a with statement)
# method 1
token = configured_asyncio.start_loop()
try:
do_something()
finally:
token.release()
# method 2
token = configured_asyncio.start_loop()
try:
do_something()
finally:
configured_asyncio.release_loop(token)
# method 3
with configured_asyncio.start_loop():
do_something()
Note
The call to start_loop
just
starts the loop, which then runs in a different thread. You must use the
asyncio.AbstractEventLoop
’s thread-safe methods to interact with
the running loop:
from asyncio import run_coroutine_threadsafe
with configured_asyncio.start_loop():
run_coroutine_threadsafe(some_coroutine, configured_asyncio.loop)
API¶
-
score.asyncio.
init
(confdict)[source] Initializes this module according to the SCORE module initialization guidelines with the following configuration keys:
- backend “builtin”
- The library to use for creating the event loop. Current valid values
are
uvloop
andbuiltin
. - use_global_loop False
- Whether the global loop object should be used. The “global” loop is the
one returned by
asyncio.get_event_loop()
. - stop_timeout None
Defines how long the module will wait for all tasks running in the loop to finish when stopping the loop. The value will be interpreted through a call to
score.init.parse_time_interval()
.The default value None indicates that the module will wait indefinitely. If you want to the loop to terminate immediately, without waiting for tasks at all, you must pass “0”.
-
class
score.asyncio.
ConfiguredAsyncioModule
[source]¶ This module’s
configuration class
.-
loop
¶ This is the configured
asyncio.AbstractEventLoop
. You should not start this loop using the defaultrun_forever()
andrun_until_complete()
methods. Use the providedstart_loop()
instead.See Starting the Loop for details.
-
start_loop
()[source]¶ Makes sure the configured
loop
is running. Will possibly start the loop in a different thread and return a loop token.This method is thread-safe.
See Starting the Loop for usage details.
-
release_loop
(token)[source]¶ Releases a previously acquired token.
See Starting the Loop for usage details.
-
await_
(coroutine)[source]¶ Blocks until given coroutine is finished and returns the result (or raises the exception).
This method will acquire a loop token, schedule the coroutine for execution in the configured event loop, await its termination and return the result (or raise the exception).
This is very similar to the builtin method
asyncio.AbstractEventLoop.run_until_complete()
, but will work when different clients try to execute a coroutine simultanously, regardless of the current loop state:>>> import asyncio >>> @asyncio.coroutine ... def foo(): ... return 1 ... >>> @asyncio.coroutine ... def bar(): ... return 1 / 0 ... >>> foo() <generator object foo at 0x7fea86b20e08> >>> score.asyncio.await_(foo()) 1 >>> score.asyncio.await_.(bar()) Traceback (most recent call last): File "<console>", line 1, in <module> File "/home/can/Projects/score/py.asyncio/score/asyncio/_init.py", line 107, in await_ return self.loop.run_until_complete(coroutine) File "/usr/lib/python3.6/asyncio/base_events.py", line 467, in run_until_complete return future.result() File "/usr/lib/python3.6/asyncio/coroutines.py", line 210, in coro res = func(*args, **kw) File "<console>", line 3, in bar ZeroDivisionError: division by zero
-
await_multiple
(coroutines)[source]¶ Just like
await_()
, but awaits the completion of multiple coroutines. The return value is different though: the method will provide a list of 2-tuples, where the first value is a bool indicating successful execution of the coroutine and the second value is the exception itself or the return value.Example with two coroutines, the first successfully returning
1
, while the other raising a ZeroDivisionError:[ (True, 1), (False, ZeroDivisionError('division by zero',)), ]
-
-
class
score.asyncio.
LoopToken
[source]¶ A token provided by the configured score.asyncio module. The configured asyncio will keep running as long as this token is held. Use
release()
to indicate that you’re done using the loop.-
release
()[source]¶ Releases this token.
See Starting the Loop for details.
-