gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-05 00:10:31 27 4
gpt4 key购买 nike

我目前正在执行 python3 asyncio 中的子进程任务。我的代码只是写入标准输入并同时读取标准输出/标准错误:

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 document page 上看到了警告:

Warning Use the communicate() method rather than process.stdin.write(), await process.stdout.read() or await process.stderr.read. This avoids deadlocks due to streams pausing reading or writing and blocking the child process.



这是否意味着上面的代码在某些情况下会陷入僵局?如果是的话怎么写 stdin并阅读 stdout/ stderr连续在python3 asyncio中没有死锁?

非常感谢你。

最佳答案

警告是从 regular 转移过来的。 subprocess 模块,并警告尝试实现看起来完全正确的简单通信的幼稚代码,例如:

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

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

您的代码没有这个问题,仅仅是因为您的读取和写入是并行执行的。由于读者从不等待作者,反之亦然,因此(那种)死锁没有机会。如果你看看如何 communicateimplemented ,你会发现,除了一些调试日志之外,它的工作方式与你的代码非常相似。

关于Python asyncio子进程连续写入stdin和读取stdout/stderr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57730010/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com