Runners¶
Source code:Lib/asyncio/runners.py
This section outlines high-level asyncio primitives to run asyncio code.
They are built on top of anevent loop with the aimto simplify async code usage for common wide-spread scenarios.
Running an asyncio Program¶
- asyncio.run(coro,*,debug=None,loop_factory=None)¶
Execute thecoroutinecoro and return the result.
This function runs the passed coroutine, taking care ofmanaging the asyncio event loop,finalizing asynchronousgenerators, and closing the executor.
This function cannot be called when another asyncio event loop isrunning in the same thread.
Ifdebug is
True
, the event loop will be run in debug mode.False
disablesdebug mode explicitly.None
is used to respect the globalDebug Mode settings.Ifloop_factory is not
None
, it is used to create a new event loop;otherwiseasyncio.new_event_loop()
is used. The loop is closed at the end.This function should be used as a main entry point for asyncio programs,and should ideally only be called once. It is recommended to useloop_factory to configure the event loop instead of policies.Passingasyncio.EventLoop
allows running asyncio without thepolicy system.The executor is given a timeout duration of 5 minutes to shutdown.If the executor hasn’t finished within that duration, a warning isemitted and the executor is closed.
Example:
asyncdefmain():awaitasyncio.sleep(1)print('hello')asyncio.run(main())
Added in version 3.7.
Changed in version 3.9:Updated to use
loop.shutdown_default_executor()
.Changed in version 3.10:debug is
None
by default to respect the global debug mode settings.Changed in version 3.12:Addedloop_factory parameter.
Runner context manager¶
- classasyncio.Runner(*,debug=None,loop_factory=None)¶
A context manager that simplifiesmultiple async function calls in the samecontext.
Sometimes several top-level async functions should be called in the sameeventloop and
contextvars.Context
.Ifdebug is
True
, the event loop will be run in debug mode.False
disablesdebug mode explicitly.None
is used to respect the globalDebug Mode settings.loop_factory could be used for overriding the loop creation.It is the responsibility of theloop_factory to set the created loop as thecurrent one. By default
asyncio.new_event_loop()
is used and set ascurrent event loop withasyncio.set_event_loop()
ifloop_factory isNone
.Basically,
asyncio.run()
example can be rewritten with the runner usage:asyncdefmain():awaitasyncio.sleep(1)print('hello')withasyncio.Runner()asrunner:runner.run(main())
Added in version 3.11.
- run(coro,*,context=None)¶
Run acoroutinecoro in the embedded loop.
Return the coroutine’s result or raise its exception.
An optional keyword-onlycontext argument allows specifying acustom
contextvars.Context
for thecoro to run in.The runner’s default context is used ifNone
.This function cannot be called when another asyncio event loop isrunning in the same thread.
- close()¶
Close the runner.
Finalize asynchronous generators, shutdown default executor, close the event loopand release embedded
contextvars.Context
.
- get_loop()¶
Return the event loop associated with the runner instance.
Note
Runner
uses the lazy initialization strategy, its constructor doesn’tinitialize underlying low-level structures.Embeddedloop andcontext are created at the
with
body enteringor the first call ofrun()
orget_loop()
.
Handling Keyboard Interruption¶
Added in version 3.11.
Whensignal.SIGINT
is raised byCtrl-C,KeyboardInterrupt
exception is raised in the main thread by default. However this doesn’t work withasyncio
because it can interrupt asyncio internals and can hang the program fromexiting.
To mitigate this issue,asyncio
handlessignal.SIGINT
as follows:
asyncio.Runner.run()
installs a customsignal.SIGINT
handler beforeany user code is executed and removes it when exiting from the function.The
Runner
creates the main task for the passed coroutine for itsexecution.When
signal.SIGINT
is raised byCtrl-C, the custom signal handlercancels the main task by callingasyncio.Task.cancel()
which raisesasyncio.CancelledError
inside the main task. This causes the Python stackto unwind,try/except
andtry/finally
blocks can be used for resourcecleanup. After the main task is cancelled,asyncio.Runner.run()
raisesKeyboardInterrupt
.A user could write a tight loop which cannot be interrupted by
asyncio.Task.cancel()
, in which case the second followingCtrl-Cimmediately raises theKeyboardInterrupt
without cancelling the main task.