python子进程模块:循环遍历子进程的stdout

时间:2009-08-14 13:34:20

标签: python subprocess

我有一些使用子进程模块运行的命令。然后我想循环输出的行。文档说不要做data_stream.stdout.read我不是,但我可能正在做一些调用它的东西。我循环输出如下:

for line in data_stream.stdout:
   #do stuff here
   .
   .
   .

这会导致死锁,例如从data_stream.stdout读取,还是为这种循环设置了Popen模块,以便它使用通信代码但是为你处理它的所有调用?

4 个答案:

答案 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很好用,如果数据量不是太大而不适合内存(如果是,你仍然可以“手动”达到相同的效果)。

如果您需要更精细的互动,请改为pexpect,或者如果您使用的是wexpect,请查看。

答案 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你应该用来做你的东西。