繁体   English   中英

Python asyncio子进程连续写入stdin和读取stdout / stderr

[英]Python asyncio subprocess write stdin and read stdout/stderr continuously

我目前正在使用python3 asyncio中的子流程执行任务。 我的代码只是简单地写入stdin并同时读取stdout / stderr:

import asyncio


async def read_stdout(stdout):
    print('read_stdout')
    while True:
        buf = await stdout.read(10)
        if not buf:
            break

        print(f'stdout: { buf }')


async def read_stderr(stderr):
    print('read_stderr')
    while True:
        buf = await stderr.read()
        if not buf:
            break

        print(f'stderr: { buf }')


async def write_stdin(stdin):
    print('write_stdin')
    for i in range(100):
        buf = f'line: { i }\n'.encode()
        print(f'stdin: { buf }')

        stdin.write(buf)
        await stdin.drain()
        await asyncio.sleep(0.5)


async def run():
    proc = await asyncio.create_subprocess_exec(
        '/usr/bin/tee',
        stdin=asyncio.subprocess.PIPE,
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE)

    await asyncio.gather(
        read_stderr(proc.stderr),
        read_stdout(proc.stdout),
        write_stdin(proc.stdin))


asyncio.run(run())

它工作得很好,但是我在Python3文档页面上看到警告:

Warning请使用communicate()方法,而不要使用process.stdin.write()await process.stdout.read()await process.stderr.read 这避免了由于流暂停读取或写入以及阻止子进程而导致的死锁。

这是否意味着上述代码在某些情况下会陷入僵局? 如果是这样,如何在python3 asyncio中连续写stdin和读取stdout / stderr而没有死锁?

非常感谢你。

该警告已从常规子过程模块中保留下来,并警告那些试图实施看起来完全正确的简单通信的幼稚代码,例如:

# write the request to the subprocess
await proc.stdin.write(request)
# read the response
response = await proc.stdout.readline()

如果子进程在读取整个请求之前开始写响应,则可能导致死锁。 如果响应足够大,则子进程将阻塞,等待父进程读取其中的一部分并在管道缓冲区中腾出空间。 但是,父级无法这样做,因为它仍在写入响应并在开始读取之前等待写入完成。 因此,子级等待父级读取(某些)响应,而父级则等待子级完成接受请求。 由于双方都在等待对方当前的操作完成,因此这是一个僵局。

您的代码不仅仅因为您的读取和写入是并行执行的,所以就没有这个问题。 由于读者从不等待作家,反之亦然,因此没有机会陷入那种僵局。 如果您查看communicate实现方式 ,您会发现,除一些调试日志记录外,它的工作原理与您的代码非常相似。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM