我有一个 long_task
函数,它运行大量 cpu 绑定(bind)计算,我想通过使用新的 asyncio 框架使其异步。生成的 long_task_async
函数使用 ProcessPoolExecutor
将工作卸载到不同的进程,从而不受 GIL 的约束。
问题在于,出于某种原因,从 ProcessPoolExecutor.submit
返回的 concurrent.futures.Future
实例在产生时会抛出一个 TypeError
。这是设计使然吗?这些 future 与 asyncio.Future
类不兼容吗?有什么解决方法?
我还注意到生成器不可 picklable,因此将协程提交给 ProcessPoolExecutor
将会失败。是否也有任何干净的解决方案?
import asyncio
from concurrent.futures import ProcessPoolExecutor
@asyncio.coroutine
def long_task():
yield from asyncio.sleep(4)
return "completed"
@asyncio.coroutine
def long_task_async():
with ProcessPoolExecutor(1) as ex:
return (yield from ex.submit(long_task)) #TypeError: 'Future' object is not iterable
# long_task is a generator, can't be pickled
loop = asyncio.get_event_loop()
@asyncio.coroutine
def main():
n = yield from long_task_async()
print( n )
loop.run_until_complete(main())
最佳答案
您想使用 loop.run_in_executor
,它使用 concurrent.futures
执行器,但将返回值映射到 asyncio
future 。
原始 asyncio
PEP suggests that concurrent.futures.Future
有朝一日可能会生成一个 __iter__
方法,这样它也可以与 yield from
一起使用,但目前该库已经旨在仅需要 yield from
支持,仅此而已。 (否则某些代码实际上不会在 3.3 中运行。)
关于python - asyncio yield from concurrent.futures.Future 执行者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22445054/