非同步執行器

注意:使用 Python 3.5+ async / await 語法

asyncio 支援使用 concurrent.futures 中的 Executor 物件非同步排程任務。事件迴圈具有 run_in_executor() 函式,它接受 Executor 物件,Callable 和 Callable 的引數。

Executor 安排任務

import asyncio
from concurrent.futures import ThreadPoolExecutor

def func(a, b):
    # Do time intensive stuff...
    return a + b

async def main(loop):
    executor = ThreadPoolExecutor()
    result = await loop.run_in_executor(executor, func, "Hello,", " world!")
    print(result)

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(loop))

每個事件迴圈還有一個預設Executor 插槽,可以分配給 Executor。要從迴圈中分配 Executor 並安排任務,請使用 set_default_executor() 方法。

import asyncio
from concurrent.futures import ThreadPoolExecutor

def func(a, b):
    # Do time intensive stuff...
    return a + b

async def main(loop):
    # NOTE: Using `None` as the first parameter designates the `default` Executor.
    result = await loop.run_in_executor(None, func, "Hello,", " world!")
    print(result)

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.set_default_executor(ThreadPoolExecutor())
    loop.run_until_complete(main(loop))

concurrent.futures 中有兩種主要型別的 ExecutorThreadPoolExecutorProcessPoolExecutorThreadPoolExecutor 包含一個執行緒池,可以通過建構函式手動設定為特定數量的執行緒,也可以預設為機器上的核心數量為 5. ThreadPoolExecutor 使用執行緒池來執行分配給它的任務,並且通常更好地在 CPU 繫結操作而不是 I / O 繫結操作。與 ProcessPoolExecutor 形成對比,ProcessPoolExecutor 為分配給它的每個任務產生一個新程序。ProcessPoolExecutor 只能接受可選擇的任務和引數。最常見的不可修復任務是物件的方法。如果必須將物件的方法安排為 Executor 中的任務,則必須使用 ThreadPoolExecutor