Runners (執行器)¶
這個章節概述用於執行 asyncio 程式碼的高階 asyncio 原始物件。
他們是基於一個事件迴圈,目的是為了簡化常見且廣泛運用場景的非同步程式碼。
運行一個 asyncio 程式¶
- asyncio.run(coro,*,debug=None,loop_factory=None)¶
執行協程 (coroutine)coro 並回傳結果。
這個函式負責運行被傳入的協程、管理 asyncio 的事件迴圈、終結非同步產生器,以及關閉執行器。
當另一個非同步事件迴圈在同一執行緒中執行時,無法呼叫此函式。
如果debug 為
True
,事件迴圈會以除錯模式執行。False
則會關閉除錯模式。None
則會優先使用除錯模式的全域設定。如果loop_factory 不為
None
,它會被用於建立一個新的事件迴圈;否則會改用asyncio.new_event_loop()
。迴圈會在最後關閉。這個函式應該要作為asyncio 程式的主要進入點,且理想上僅會被呼叫一次。推薦使用loop_factory 來設定事件迴圈時而不是使用 policies(政策)。傳遞asyncio.EventLoop
可以讓 asyncio 在沒有政策系統的情況下運行。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.
範例:
asyncdefmain():awaitasyncio.sleep(1)print('hello')asyncio.run(main())
在 3.7 版被加入.
在 3.9 版的變更:Updated to use
loop.shutdown_default_executor()
.在 3.10 版的變更:debug is
None
by default to respect the global debug mode settings.在 3.12 版的變更:新增loop_factory 參數。
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
.如果debug 為
True
,事件迴圈會以除錯模式執行。False
則會關閉除錯模式。None
則會優先使用除錯模式的全域設定。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())
在 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
.當另一個非同步事件迴圈在同一執行緒中執行時,無法呼叫此函式。
- 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.
備註
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¶
在 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.