如何结合使用python asyncio和多重处理?

时间:2019-07-09 01:31:35

标签: python python-multiprocessing python-asyncio

我有一个需要多处理才能处理CPU绑定的反序列化和传入数据解码的设备;但是应用程序的其余部分是速度较慢的IO限制代码,这对asyncio来说非常有用。但是,似乎没有将多处理和异步结合在一起的好方法。

我尝试过https://github.com/dano/aioprocessing,它使用线程执行程序进行多处理操作。但是,此库本身不支持常见的异步操作;例如,取消与此库一起在queue.get上等待的例程将导致死锁。

我也尝试过使用ProcessPoolExecutor,但是将多处理对象传递给该执行程序不起作用,因为在创建进程时未传递队列对象。

import multiprocessing
import asyncio
import atexit
from concurrent.futures import ProcessPoolExecutor


@atexit.register
def kill_children():
    [p.kill() for p in multiprocessing.active_children()]


async def queue_get(queue: multiprocessing.Queue):
    executor = ProcessPoolExecutor(max_workers=1)
    loop = asyncio.get_running_loop()
    return await loop.run_in_executor(executor, queue.get)


async def main():
    queue = multiprocessing.Queue()
    get_task = asyncio.create_task(queue_get(queue))

    queue.put(None)

    print(await get_task)


if __name__ == "__main__":
    asyncio.run(main())

运行此代码会导致以下异常:

RuntimeError: Queue objects should only be shared between processes through inheritance

有什么方法可以消除多处理与异步之间的鸿沟吗?

1 个答案:

答案 0 :(得分:0)

Can I somehow share an asynchronous queue with a subprocess?

可以通过通过multiprocessing.Manager()创建队列,以修改上面的代码以与多处理队列一起使用

import multiprocessing
import asyncio
import atexit
from concurrent.futures import ProcessPoolExecutor


@atexit.register
def kill_children():
    [p.kill() for p in multiprocessing.active_children()]


async def queue_get(queue: multiprocessing.Queue):
    executor = ProcessPoolExecutor(max_workers=1)
    loop = asyncio.get_running_loop()
    return await loop.run_in_executor(executor, queue.get)


async def main():
    manager = multiprocessing.Manager()
    queue = manager.Queue()
    get_task = asyncio.create_task(queue_get(queue))

    queue.put(None)
    print(await get_task)


if __name__ == "__main__":
    asyncio.run(main())