我有一些使用子进程模块运行的命令。然后我想循环输出的行。文档说不要做data_stream.stdout.read我不是,但我可能正在做一些调用它的东西。我循环输出如下:
for line in data_stream.stdout:
#do stuff here
.
.
.
这会导致死锁,例如从data_stream.stdout读取,还是为这种循环设置了Popen模块,以便它使用通信代码但是为你处理它的所有调用?
答案 0 :(得分:6)
如果您与子进程通信,则必须担心死锁,即如果您正在写入stdin以及从stdout读取。因为这些管道可能被缓存,所以进行这种双向通信是非常禁止的:
data_stream = Popen(mycmd, stdin=PIPE, stdout=PIPE)
data_stream.stdin.write("do something\n")
for line in data_stream:
... # BAD!
但是,如果在构造data_stream时没有设置stdin(或stderr),那么你应该没问题。
data_stream = Popen(mycmd, stdout=PIPE)
for line in data_stream.stdout:
... # Fine
如果您需要双向通信,请使用communicate。
答案 1 :(得分:6)
这两个答案已经很好地抓住了这个问题的要点:不要把东西写入子进程,从中读取内容,再次写入等等 - 管道的缓冲意味着你有陷入僵局的风险。如果可以,写下你需要写入子进程FIRST的所有内容,关闭该管道,然后只读取子进程必须说的所有内容; communicate
很好用,如果数据量不是太大而不适合内存(如果是,你仍然可以“手动”达到相同的效果)。
答案 2 :(得分:3)
如果你的子进程有一个小到中等的输出量,那么SilentGhost的/ chrispy的答案是可以的。但有时候,可能会有很多输出 - 太多而无法在内存中缓慢缓冲。在这种情况下,要做的是start()
进程,并产生几个线程 - 一个用于阅读child.stdout
,另一个用于阅读child.stderr
,其中child
是子。然后,您需要wait()
来终止子进程。
这实际上是communicate()
的工作原理;使用自己的线程的好处是可以在生成时处理子进程的输出。例如,在我的项目python-gnupg
中,我使用此技术从GnuPG可执行文件生成时读取状态输出,而不是通过调用communicate()
等待所有这些输出。欢迎您检查此项目的来源 - 相关内容在模块gnupg.py
中。
答案 3 :(得分:0)
data_stream.stdout
是标准输出句柄。你不应该循环它。 communicate
返回(stdoutdata, stderr)
的元组。这个stdoutdata
你应该用来做你的东西。