当我提到这个问题时,我期望答案真的使用asyncio进行进程间通信。
我已经发现以下资源有用: https://github.com/python/asyncio/blob/master/examples/child_process.py
并且在下面我的简化的例子(使用3.5+异步/ AWAIT语法),其内容为线,并输出它们来分类:
import asyncio
from subprocess import Popen, PIPE
async def connect_write_pipe(file):
"""Return a write-only transport wrapping a writable pipe"""
loop = asyncio.get_event_loop()
transport, _ = await loop.connect_write_pipe(asyncio.Protocol, file)
return transport
async def connect_read_pipe(file):
"""Wrap a readable pipe in a stream"""
loop = asyncio.get_event_loop()
stream_reader = asyncio.StreamReader(loop=loop)
def factory():
return asyncio.StreamReaderProtocol(stream_reader)
transport, _ = await loop.connect_read_pipe(factory, file)
return stream_reader, transport
async def main(loop):
# start subprocess and wrap stdin, stdout, stderr
p = Popen(['/usr/bin/sort'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
stdin = await connect_write_pipe(p.stdin)
stdout, stdout_transport = await connect_read_pipe(p.stdout)
stderr, stderr_transport = await connect_read_pipe(p.stderr)
# interact with subprocess
name = {stdout: 'OUT', stderr: 'ERR'}
registered = {
asyncio.Task(stderr.read()): stderr,
asyncio.Task(stdout.read()): stdout
}
to_sort = b"one\ntwo\nthree\n"
stdin.write(to_sort)
stdin.close() # this way we tell we do not have anything else
# get and print lines from stdout, stderr
timeout = None
while registered:
done, pending = await asyncio.wait(
registered, timeout=timeout,
return_when=asyncio.FIRST_COMPLETED)
if not done:
break
for f in done:
stream = registered.pop(f)
res = f.result()
if res != b'':
print(name[stream], res.decode('ascii').rstrip())
registered[asyncio.Task(stream.read())] = stream
timeout = 0.0
stdout_transport.close()
stderr_transport.close()
if __name__ == '__main__':
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(main(loop))
finally:
loop.close()
NB :没有采取特殊措施,要写入管道的数据量是有限的。在我的系统中,在使用管道缓冲区之前,可以写入超过700000字节。
那里还有其他的例子,使用create_subprocess_shell
。
我还没有在真实项目中使用asyncio,所以欢迎评论中的改进建议。
问题是什么? –
这不会异步运行。它等待这个过程完成,但我希望它在此期间运行其他的东西。所以就像我先调用这个函数,然后调用另一个函数,这个函数大约需要20s,另一个大约需要2s。第二个func在跑之前必须等待20秒。 – init6
你有避免多线程的理由吗? –