首页 > 解决方案 > 为什么 asyncio 被 processPool 阻塞?

问题描述

我有以下代码:

import time
import asyncio
from concurrent.futures import ProcessPoolExecutor

def blocking_func(x):
    print("In blocking waiting")
    time.sleep(x) # Pretend this is expensive calculations
    print("after blocking waiting")
    return x * 5

@asyncio.coroutine
def main():
    executor = ProcessPoolExecutor()

    out = yield from loop.run_in_executor(executor, blocking_func, 2)  # This does not
    print("after process pool")
    print(out)

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

输出:

In blocking waiting
after blocking waiting
after process pool
10

但我期待进程池将在不同的进程中运行代码。所以我期望输出是:

期望输出:

In blocking waiting
after process pool
after blocking waiting
10

我想如果我们在进程池上运行代码它不会阻塞主循环。但是在输出中它在完成阻塞功能后又回到了主事件循环。

是什么阻止了事件循环?是blocking_function吗?如果是blocking_function,拥有进程池有什么用?

标签: python-3.xasynchronouspython-asyncio

解决方案


yield from这里的意思是“等待协程完成并返回结果”。与 Python 线程 API 相比,它就像调用join().

要获得所需的结果,请使用以下内容:

@asyncio.coroutine
def main():
    executor = ProcessPoolExecutor()

    task = loop.run_in_executor(executor, blocking_func, 2)
    # at this point your blocking func is already running
    # in the executor process

    print("after process pool")

    out = yield from task

    print(out)

推荐阅读