Python asyncio子进程连续写入stdin和读取stdout/stderr
我目前正在执行python3 asyncio中的子进程任务。我的代码只需同时写入stdin和读取stdout/stderr即可:Python asyncio子进程连续写入stdin和读取stdout/stderr,python,python-3.x,subprocess,python-asyncio,Python,Python 3.x,Subprocess,Python Asyncio,我目前正在执行python3 asyncio中的子进程任务。我的代码只需同时写入stdin和读取stdout/stderr即可: 导入异步IO 异步def读取标准输出(标准输出): 打印('read_stdout') 尽管如此: buf=等待标准读取(10) 如果不是buf: 打破 打印(f'stdout:{buf}') 异步def read_stderr(stderr): 打印('read_stderr') 尽管如此: buf=wait stderr.read() 如果不是buf: 打破 打印
导入异步IO
异步def读取标准输出(标准输出):
打印('read_stdout')
尽管如此:
buf=等待标准读取(10)
如果不是buf:
打破
打印(f'stdout:{buf}')
异步def read_stderr(stderr):
打印('read_stderr')
尽管如此:
buf=wait stderr.read()
如果不是buf:
打破
打印(f'stderr:{buf}')
异步def写入标准数据(标准数据):
打印('write_stdin')
对于范围(100)内的i:
buf=f'line:{i}\n'.encode()
打印(f'stdin:{buf}')
标准写入(buf)
等待标准排水管()
等待异步睡眠(0.5)
异步def run():
proc=wait asyncio.create_subprocess_exec(
“/usr/bin/tee”,
stdin=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE)
等待asyncio.gather(
读取标准(程序标准),
读标准(程序标准),
写入标准(过程标准))
asyncio.run(run())
它工作得很好,但我看到一个警告:
Warning
使用communicate()
方法,而不是process.stdin.write()
,wait process.stdout.read()
或wait 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()
如果子进程在读取整个请求之前就开始写入响应,这可能会导致死锁。如果响应足够大,子进程将阻塞,等待父进程读取部分响应并在管道缓冲区中腾出空间。但是,父级无法执行此操作,因为它仍在写入响应,并等待写入完成后再开始读取。因此,子级等待父级读取(部分)响应,父级等待子级完成接受请求。由于双方都在等待另一方的当前操作完成,因此这是一个死锁
您的代码没有这个问题,因为您的读写是并行执行的。因为读者从不等待作者,反之亦然,所以没有机会出现(那种)僵局。如果您查看一下
通信的方式,您会发现,除了一些调试日志记录之外,它的工作原理与您的代码非常相似。通信
等待子进程终止。如果您希望多次阅读(例如,阅读内容、回复stdin、再次阅读等),则通信
根本无法使用。警告只涉及一次读取的简单情况…感谢您的回复,因此反复读取/写入不会有问题?非常感谢您提供非常详细的答案!