我可以使用asyncio读取和写入multiprocessing.Pipe吗?

时间:2019-11-05 22:58:56

标签: python python-3.x multiprocessing pipe python-asyncio

我需要在Python的进程之间进行通信,并且在每个进程中都使用asyncio进行并发网络IO。

当前,我正在multiprocessing.Pipesendrecv的两个进程之间使用大量数据,但是我在asyncio之外使用,我相信因此,我在IO_WAIT中花费了大量的CPU时间。

似乎asyncio可以并且应该用于处理进程之间的Pipe IO,但是除了管道STDIN / STDOUT之外,我找不到任何示例。

从我的阅读看来,我应该在loop.connect_read_pipe(PROTOCOL_FACTORY, PIPE)中注册管道,并同样进行写入。但是,我不了解protocol_factory的目的,因为它与multiprocessing.Pipe有关。我是否应该创建multiprocessing.Pipe还是可以在asyncio中创建管道还不清楚。

2 个答案:

答案 0 :(得分:2)

multiprocessing.Pipe使用高级multiprocessing.Connection模块来腌制和释放Python对象,并在后台传输其他字节。如果要使用loop.connect_read_pipe()从这些管道之一读取数据,则必须自己重新实现所有这些。

multiprocessing.Pipe读取而不阻塞事件循环的最简单方法是使用loop.add_reader()。考虑以下示例:

import asyncio
import multiprocessing


def main():
    read, write = multiprocessing.Pipe(duplex=False)
    writer_process = multiprocessing.Process(target=writer, args=(write,))
    writer_process.start()
    asyncio.get_event_loop().run_until_complete(reader(read))


async def reader(read):
    frame_available = asyncio.Event()
    asyncio.get_event_loop().add_reader(read.fileno(), frame_available.set)
    await frame_available.wait()
    frame_available.clear()
    print(read.recv())


def writer(write):
    write.send('Hello World')


if __name__ == '__main__':
    main()

使用较低级别的os.pipe创建的管道不会像从multiprocessing.Pipe进行管道传输那样添加任何其他内容。结果,我们可以将os.pipeloop.connect_read_pipe()结合使用,而无需重新实现任何内部工作方式。这是一个示例:

import asyncio
import multiprocessing
import os


def main():
    read, write = os.pipe()
    writer_process = multiprocessing.Process(target=writer, args=(write,))
    writer_process.start()
    asyncio.get_event_loop().run_until_complete(reader(read))


async def reader(read):
    pipe = os.fdopen(read, mode='r')

    loop = asyncio.get_event_loop()
    stream_reader = asyncio.StreamReader()
    def protocol_factory():
        return asyncio.StreamReaderProtocol(stream_reader)

    transport, _ = await loop.connect_read_pipe(protocol_factory, pipe)
    print(await stream_reader.readline())
    transport.close()


def writer(write):
    os.write(write, b'Hello World\n')


if __name__ == '__main__':
    main()

This code帮助我弄清楚了如何使用loop.connect_read_pipe

答案 1 :(得分:1)

aiopipe似乎可以满足您的要求!它可以与内置的multiprocessing模块一起使用,并提供与常规阻塞管道类似的API。