我有以下代码:
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,那么使用进程池有什么用呢?
答案 0 :(得分:2)
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)
答案 1 :(得分:1)
协同程序不是单独的进程。不同之处在于协程需要自己放弃对循环的控制。这意味着如果你有一个阻塞协程,那么它将阻止整个循环。
使用协同程序的原因主要是处理I / O活动。如果您正在等待消息,则只需检查套接字即可,如果没有任何反应,您将返回主循环。然后可以在最终控制返回到IO功能之前处理其他协同程序。
在您的情况下,使用await asyncio.sleep(x)
代替time.sleep(x)
是有意义的。这样,控制在休眠时间内从blocking_func()
暂停。然后控制返回那里,结果应该如你所愿。