【问题标题】:Usage of stdout.close() in python's subprocess module when piping管道时在 python 的子进程模块中使用 stdout.close()
【发布时间】:2014-05-29 06:36:43
【问题描述】:

在python子进程模块中,如果我们想运行shell命令

foo | grep bar

在 python 中,我们可以使用

p1 = Popen(["foo"], stdout = PIPE)
p2 = Popen(["grep", "bar"], stdin = p1.stdout, stdout = PIPE)
p1.stdout.close()
output = p2.communicate()[0]

我对@9​​87654323@ 这条线感到困惑。如果你能原谅我,我会追查我认为该程序是如何工作的,希望错误会自己暴露出来。

在我看来,当output = p2.communicate()[0] 行由python 制定时,python 尝试调用p2,它认识到它需要来自p1 的输出。所以它调用p1,它执行foo并将输出扔到堆栈上,以便p2可以完成执行。然后p2 完成。

但在此跟踪中,p1.stdout.close() 并没有真正发生。那么实际发生了什么?在我看来,这种行的顺序可能也很重要,因此以下内容不起作用:

p1 = Popen(["foo"], stdout = PIPE)
p1.stdout.close()
p2 = Popen(["grep", "bar"], stdin = p1.stdout, stdout = PIPE)
output = p2.communicate()[0]

这就是我的理解状态。

【问题讨论】:

    标签: python subprocess pipe


    【解决方案1】:

    p1.stdout.close()foo 检测管道何时损坏所必需的,例如,当p2 过早退出时。

    如果没有p1.stdout.close(),那么p1.stdout 在父进程中保持打开状态,即使p2 退出; p1 不会知道没有人读取p1.stdout,即p1 将继续写入p1.stdout,直到相应的操作系统管道缓冲区已满,然后它就会永远阻塞。

    要在没有 shell 的情况下模拟 foo | grep bar shell 命令:

    #!/usr/bin/env python3
    from subprocess import Popen, PIPE
    
    with Popen(['grep', 'bar'], stdin=PIPE) as grep, \
         Popen(['foo'], stdout=grep.stdin):
        grep.communicate()
    

    How do I use subprocess.Popen to connect multiple processes by pipes?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-18
      • 2013-08-01
      • 1970-01-01
      相关资源
      最近更新 更多