python - asyncio yield from concurrent.futures.Future 执行者

标签 python python-3.x python-asyncio concurrent.futures

我有一个 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/

相关文章:

python - 如何使用 python 计算一组 3d 点之间的距离?

python - TypeError: 'float' 对象不可下标 --Python

python-3.x - 没有名为 'pandas' 的模块 - Jupyter、Python3 内核、TensorFlow 通过 Docker

error-handling - 尝试/除了不捕捉 future 的 TimeoutError

python - asyncio.wait 顺序有保证吗?

python - 无法使用 torch.utils.tensorboard.SummaryWriter.add_graph 方法加载保存的图形

python - 如何让 Discord 机器人异步等待对多条消息的 react ?

python - 如何中止创建的协程Python

python - 大小差异从何而来?

python - 有条件地导入模块以影子本地实现