策略?

事件循環(huán)策略是各個(gè)進(jìn)程的全局對象 ,它控制事件循環(huán)的管理。每個(gè)事件循環(huán)都有一個(gè)默認(rèn)策略,可以使用策略API更改和定制該策略。

策略定義了“上下文”的概念,每個(gè)上下文管理一個(gè)單獨(dú)的事件循環(huán)。默認(rèn)策略將*context*定義為當(dāng)前線程。

通過使用自定義事件循環(huán)策略,可以自定義 get_event_loop()set_event_loop()new_event_loop() 函數(shù)的行為。

策略對象應(yīng)該實(shí)現(xiàn) AbstractEventLoopPolicy 抽象基類中定義的API。

獲取和設(shè)置策略?

可以使用下面函數(shù)獲取和設(shè)置當(dāng)前進(jìn)程的策略:

asyncio.get_event_loop_policy()?

返回當(dāng)前進(jìn)程域的策略。

asyncio.set_event_loop_policy(policy)?

policy 設(shè)置為當(dāng)前進(jìn)程域策略。

如果 policy 設(shè)為 None 將恢復(fù)默認(rèn)策略。

策略對象?

抽象事件循環(huán)策略基類定義如下:

class asyncio.AbstractEventLoopPolicy?

異步策略的抽象基類。

get_event_loop()?

為當(dāng)前上下文獲取事件循環(huán)。

返回一個(gè)實(shí)現(xiàn) AbstractEventLoop 接口的事件循環(huán)對象。

該方法永遠(yuǎn)不應(yīng)返回 None

在 3.6 版更改.

set_event_loop(loop)?

將當(dāng)前上下文的事件循環(huán)設(shè)置為 loop 。

new_event_loop()?

創(chuàng)建并返回一個(gè)新的事件循環(huán)對象。

該方法永遠(yuǎn)不應(yīng)返回 None

get_child_watcher()?

獲取子進(jìn)程監(jiān)視器對象。

返回一個(gè)實(shí)現(xiàn) AbstractChildWatcher 接口的監(jiān)視器對象。

該函數(shù)僅支持Unix。

set_child_watcher(watcher)?

將當(dāng)前子進(jìn)程監(jiān)視器設(shè)置為 watcher

該函數(shù)僅支持Unix。

asyncio附帶下列內(nèi)置策略:

class asyncio.DefaultEventLoopPolicy?

默認(rèn)的 asyncio 策略。 在 Unix 上使用 SelectorEventLoop 而在 Windows 上使用 ProactorEventLoop。

不需要手動安裝默認(rèn)策略。asyncio已配置成自動使用默認(rèn)策略。

在 3.8 版更改: 在 Windows 上,現(xiàn)在默認(rèn)會使用 ProactorEventLoop。

class asyncio.WindowsSelectorEventLoopPolicy?

一個(gè)使用 SelectorEventLoop 事件循環(huán)實(shí)現(xiàn)的替代事件循環(huán)策略。

可用性: Windows。

class asyncio.WindowsProactorEventLoopPolicy?

使用 ProactorEventLoop 事件循環(huán)實(shí)現(xiàn)的另一種事件循環(huán)策略。

可用性: Windows。

進(jìn)程監(jiān)視器?

進(jìn)程監(jiān)視器允許定制事件循環(huán)如何監(jiān)視Unix子進(jìn)程。具體來說,事件循環(huán)需要知道子進(jìn)程何時(shí)退出。

在asyncio中子進(jìn)程由 create_subprocess_exec()loop.subprocess_exec() 函數(shù)創(chuàng)建。

asyncio 定義了 AbstractChildWatcher 抽象基類,子監(jiān)視器必須要實(shí)現(xiàn)它,并具有四種不同實(shí)現(xiàn): ThreadedChildWatcher (已配置為默認(rèn)使用), MultiLoopChildWatcher, SafeChildWatcherFastChildWatcher

請參閱 子進(jìn)程和線程 部分。

以下兩個(gè)函數(shù)可用于自定義子進(jìn)程監(jiān)視器實(shí)現(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è)置為 watcherwatcher 必須實(shí)現(xiàn) AbstractChildWatcher 基類定義的方法。

備注

第三方事件循環(huán)實(shí)現(xiàn)可能不支持自定義子監(jiān)視器。對于這樣的事件循環(huán),禁止使用 set_child_watcher() 或不起作用。

class asyncio.AbstractChildWatcher?
add_child_handler(pid, callback, *args)?

注冊一個(gè)新的子處理回調(diào)函數(shù)。

安排 callback(pid, returncode, *args) 在進(jìn)程的PID與 pid 相等時(shí)調(diào)用。指定另一個(gè)同進(jìn)程的回調(diào)函數(shù)替換之前的回調(diào)處理函數(shù)。

回調(diào)函數(shù) callback 必須是線程安全。

remove_child_handler(pid)?

刪除進(jìn)程PID與 pid 相等的進(jìn)程的處理函數(shù)。

處理函數(shù)成功刪除時(shí)返回 True ,沒有刪除時(shí)返回 False 。

attach_loop(loop)?

給一個(gè)事件循環(huán)綁定監(jiān)視器。

如果監(jiān)視器之前已綁定另一個(gè)事件循環(huán),那么在綁定新循環(huán)前會先解綁原來的事件循環(huán)。

注意:循環(huán)有可能是 None 。

is_active()?

如果監(jiān)視器已準(zhǔn)備好使用則返回 True。

使用 不活動的 當(dāng)前子監(jiān)視器生成子進(jìn)程將引發(fā) RuntimeError。

3.8 新版功能.

close()?

關(guān)閉監(jiān)視器。

必須調(diào)用這個(gè)方法以確保相關(guān)資源會被清理。

class asyncio.ThreadedChildWatcher?

此實(shí)現(xiàn)會為每個(gè)生成的子進(jìn)程啟動一具新的等待線程。

即使是當(dāng) asyncio 事件循環(huán)運(yùn)行在非主 OS 線程上時(shí)它也能可靠地工作。

當(dāng)處理大量子進(jìn)程時(shí)不存在顯著的開銷 (每次子進(jìn)程結(jié)束時(shí)為 O(1)),但當(dāng)每個(gè)進(jìn)程啟動一個(gè)線程時(shí)則需要額外的內(nèi)存。

此監(jiān)視器會默認(rèn)被使用。

3.8 新版功能.

class asyncio.MultiLoopChildWatcher?

此實(shí)現(xiàn)會在實(shí)例化時(shí)注冊一個(gè) SIGCHLD 信號處理程序。 這可能會破壞為 SIGCHLD 信號安裝自定義處理程序的第三方代碼。

此監(jiān)視器會在收到 SIGCHLD 信號時(shí)通過顯式地輪詢每個(gè)進(jìn)程來避免干擾其他代碼生成的進(jìn)程。

該監(jiān)視器一旦被安裝就不會限制從不同線程運(yùn)行子進(jìn)程。

該解決方案是安全的,但在處理大量進(jìn)程時(shí)會有顯著的開銷 (每收到一個(gè) SIGCHLD 時(shí)為 O(n))。

3.8 新版功能.

class asyncio.SafeChildWatcher?

該實(shí)現(xiàn)會使用主線程中的活動事件循環(huán)來處理 SIGCHLD 信號。 如果主線程沒有正在運(yùn)行的事件循環(huán),則其他線程無法生成子進(jìn)程 (會引發(fā) RuntimeError)。

此監(jiān)視器會在收到 SIGCHLD 信號時(shí)通過顯式地輪詢每個(gè)進(jìn)程來避免干擾其他代碼生成的進(jìn)程。

該解決方案與 MultiLoopChildWatcher 同樣安全并同樣具有 O(N) 復(fù)雜度,但需要主線程有正在運(yùn)行的事件循環(huán)才能工作。

class asyncio.FastChildWatcher?

這種實(shí)現(xiàn)直接調(diào)用 os.waitpid(-1) 來獲取所有已結(jié)束的進(jìn)程,可能會中斷其它代碼洐生進(jìn)程并等待它們結(jié)束。

在處理大量子監(jiān)視器時(shí)沒有明顯的開銷( O(1) 每次子監(jiān)視器結(jié)束)。

該解決方案需要主線程有正在運(yùn)行的事件循環(huán)才能工作,這與 SafeChildWatcher 一樣。

class asyncio.PidfdChildWatcher?

這個(gè)實(shí)現(xiàn)會輪詢處理文件描述符 (pidfds) 以等待子進(jìn)程終結(jié)。 在某些方面,PidfdChildWatcher 是一個(gè)“理想的”子進(jìn)程監(jiān)視器實(shí)現(xiàn)。 它不需要使用信號或線程,不會介入任何在事件循環(huán)以外發(fā)起的進(jìn)程,并能隨事件循環(huán)發(fā)起的子進(jìn)程數(shù)量進(jìn)行線性伸縮。 其主要缺點(diǎn)在于 pidfds 是 Linux 專屬的,并且僅在較近版本的核心(5.3+)上可用。

3.9 新版功能.

自定義策略?

要實(shí)現(xiàn)一個(gè)新的事件循環(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())