策略?
事件循環(huán)策略是各個進程的全局對象 ,它控制事件循環(huán)的管理。每個事件循環(huán)都有一個默認策略,可以使用策略API更改和定制該策略。
策略定義了“上下文”的概念,每個上下文管理一個單獨的事件循環(huán)。默認策略將*context*定義為當(dāng)前線程。
通過使用自定義事件循環(huán)策略,可以自定義 get_event_loop()
、 set_event_loop()
和 new_event_loop()
函數(shù)的行為。
策略對象應(yīng)該實現(xiàn) AbstractEventLoopPolicy
抽象基類中定義的API。
獲取和設(shè)置策略?
可以使用下面函數(shù)獲取和設(shè)置當(dāng)前進程的策略:
- asyncio.get_event_loop_policy()?
返回當(dāng)前進程域的策略。
- asyncio.set_event_loop_policy(policy)?
將 policy 設(shè)置為當(dāng)前進程域策略。
如果 policy 設(shè)為
None
將恢復(fù)默認策略。
策略對象?
抽象事件循環(huán)策略基類定義如下:
- class asyncio.AbstractEventLoopPolicy?
異步策略的抽象基類。
- get_event_loop()?
為當(dāng)前上下文獲取事件循環(huán)。
返回一個實現(xiàn)
AbstractEventLoop
接口的事件循環(huán)對象。該方法永遠不應(yīng)返回
None
。在 3.6 版更改.
- set_event_loop(loop)?
將當(dāng)前上下文的事件循環(huán)設(shè)置為 loop 。
- new_event_loop()?
創(chuàng)建并返回一個新的事件循環(huán)對象。
該方法永遠不應(yīng)返回
None
。
- get_child_watcher()?
獲取子進程監(jiān)視器對象。
返回一個實現(xiàn)
AbstractChildWatcher
接口的監(jiān)視器對象。該函數(shù)僅支持Unix。
- set_child_watcher(watcher)?
將當(dāng)前子進程監(jiān)視器設(shè)置為 watcher 。
該函數(shù)僅支持Unix。
asyncio附帶下列內(nèi)置策略:
- class asyncio.DefaultEventLoopPolicy?
默認的 asyncio 策略。 在 Unix 上使用
SelectorEventLoop
而在 Windows 上使用ProactorEventLoop
。不需要手動安裝默認策略。asyncio已配置成自動使用默認策略。
在 3.8 版更改: 在 Windows 上,現(xiàn)在默認會使用
ProactorEventLoop
。
- class asyncio.WindowsSelectorEventLoopPolicy?
一個使用
SelectorEventLoop
事件循環(huán)實現(xiàn)的替代事件循環(huán)策略。可用性: Windows。
- class asyncio.WindowsProactorEventLoopPolicy?
使用
ProactorEventLoop
事件循環(huán)實現(xiàn)的另一種事件循環(huán)策略。可用性: Windows。
進程監(jiān)視器?
進程監(jiān)視器允許定制事件循環(huán)如何監(jiān)視Unix子進程。具體來說,事件循環(huán)需要知道子進程何時退出。
在asyncio中子進程由 create_subprocess_exec()
和 loop.subprocess_exec()
函數(shù)創(chuàng)建。
asyncio 定義了 AbstractChildWatcher
抽象基類,子監(jiān)視器必須要實現(xiàn)它,并具有四種不同實現(xiàn): ThreadedChildWatcher
(已配置為默認使用), MultiLoopChildWatcher
, SafeChildWatcher
和 FastChildWatcher
。
請參閱 子進程和線程 部分。
以下兩個函數(shù)可用于自定義子進程監(jiān)視器實現(xiàn),它將被asyncio事件循環(huán)使用:
- asyncio.get_child_watcher()?
返回當(dāng)前策略的當(dāng)前子監(jiān)視器。
- asyncio.set_child_watcher(watcher)?
將當(dāng)前策略的子監(jiān)視器設(shè)置為 watcher 。watcher 必須實現(xiàn)
AbstractChildWatcher
基類定義的方法。
備注
第三方事件循環(huán)實現(xiàn)可能不支持自定義子監(jiān)視器。對于這樣的事件循環(huán),禁止使用 set_child_watcher()
或不起作用。
- class asyncio.AbstractChildWatcher?
- add_child_handler(pid, callback, *args)?
注冊一個新的子處理回調(diào)函數(shù)。
安排
callback(pid, returncode, *args)
在進程的PID與 pid 相等時調(diào)用。指定另一個同進程的回調(diào)函數(shù)替換之前的回調(diào)處理函數(shù)。回調(diào)函數(shù) callback 必須是線程安全。
- remove_child_handler(pid)?
刪除進程PID與 pid 相等的進程的處理函數(shù)。
處理函數(shù)成功刪除時返回
True
,沒有刪除時返回False
。
- attach_loop(loop)?
給一個事件循環(huán)綁定監(jiān)視器。
如果監(jiān)視器之前已綁定另一個事件循環(huán),那么在綁定新循環(huán)前會先解綁原來的事件循環(huán)。
注意:循環(huán)有可能是
None
。
- is_active()?
如果監(jiān)視器已準(zhǔn)備好使用則返回
True
。使用 不活動的 當(dāng)前子監(jiān)視器生成子進程將引發(fā)
RuntimeError
。3.8 新版功能.
- close()?
關(guān)閉監(jiān)視器。
必須調(diào)用這個方法以確保相關(guān)資源會被清理。
- class asyncio.ThreadedChildWatcher?
此實現(xiàn)會為每個生成的子進程啟動一具新的等待線程。
即使是當(dāng) asyncio 事件循環(huán)運行在非主 OS 線程上時它也能可靠地工作。
當(dāng)處理大量子進程時不存在顯著的開銷 (每次子進程結(jié)束時為 O(1)),但當(dāng)每個進程啟動一個線程時則需要額外的內(nèi)存。
此監(jiān)視器會默認被使用。
3.8 新版功能.
- class asyncio.MultiLoopChildWatcher?
此實現(xiàn)會在實例化時注冊一個
SIGCHLD
信號處理程序。 這可能會破壞為SIGCHLD
信號安裝自定義處理程序的第三方代碼。此監(jiān)視器會在收到
SIGCHLD
信號時通過顯式地輪詢每個進程來避免干擾其他代碼生成的進程。該監(jiān)視器一旦被安裝就不會限制從不同線程運行子進程。
該解決方案是安全的,但在處理大量進程時會有顯著的開銷 (每收到一個
SIGCHLD
時為 O(n))。3.8 新版功能.
- class asyncio.SafeChildWatcher?
該實現(xiàn)會使用主線程中的活動事件循環(huán)來處理
SIGCHLD
信號。 如果主線程沒有正在運行的事件循環(huán),則其他線程無法生成子進程 (會引發(fā)RuntimeError
)。此監(jiān)視器會在收到
SIGCHLD
信號時通過顯式地輪詢每個進程來避免干擾其他代碼生成的進程。該解決方案與
MultiLoopChildWatcher
同樣安全并同樣具有 O(N) 復(fù)雜度,但需要主線程有正在運行的事件循環(huán)才能工作。
- class asyncio.FastChildWatcher?
這種實現(xiàn)直接調(diào)用
os.waitpid(-1)
來獲取所有已結(jié)束的進程,可能會中斷其它代碼洐生進程并等待它們結(jié)束。在處理大量子監(jiān)視器時沒有明顯的開銷( O(1) 每次子監(jiān)視器結(jié)束)。
該解決方案需要主線程有正在運行的事件循環(huán)才能工作,這與
SafeChildWatcher
一樣。
- class asyncio.PidfdChildWatcher?
這個實現(xiàn)會輪詢處理文件描述符 (pidfds) 以等待子進程終結(jié)。 在某些方面,
PidfdChildWatcher
是一個“理想的”子進程監(jiān)視器實現(xiàn)。 它不需要使用信號或線程,不會介入任何在事件循環(huán)以外發(fā)起的進程,并能隨事件循環(huán)發(fā)起的子進程數(shù)量進行線性伸縮。 其主要缺點在于 pidfds 是 Linux 專屬的,并且僅在較近版本的核心(5.3+)上可用。3.9 新版功能.
自定義策略?
要實現(xiàn)一個新的事件循環(huán)策略,建議子類化 DefaultEventLoopPolicy
并重寫需要定制行為的方法,例如:
class MyEventLoopPolicy(asyncio.DefaultEventLoopPolicy):
def get_event_loop(self):
"""Get the event loop.
This may be None or an instance of EventLoop.
"""
loop = super().get_event_loop()
# Do something with loop ...
return loop
asyncio.set_event_loop_policy(MyEventLoopPolicy())