代码之家  ›  专栏  ›  技术社区  ›  dhg

子进程.Popen.communicate()中的管道断裂,带有标准DIN

  •  3
  • dhg  · 技术社区  · 16 年前

    我在使用subprocess.Popen.communicate()时遇到了一个奇怪的问题。在后台,我想从python脚本执行一个应用程序。当我从命令行运行程序时,我是这样做的(UNIX):

    $ echo "input text" | /path/to/myapp
    

    在我的脚本中,我还希望通过管道将输入传输到应用程序中。因此,我尝试了以下方法。但是,当我尝试使用communicate()发送输入时,出现“断管”错误:

    >>> cmd = ['/path/to/myapp']
    >>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE)
    >>> out,err = p.communicate('input text')
    Traceback (most recent call last):
      File "", line 1, in 
      File "/usr/lib/python2.5/subprocess.py", line 670, in communicate
        return self._communicate(input)
      File "/usr/lib/python2.5/subprocess.py", line 1223, in _communicate
        bytes_written = self._write_no_intr(self.stdin.fileno(), buffer(input, input_offset, 512))
      File "/usr/lib/python2.5/subprocess.py", line 1003, in _write_no_intr
        return os.write(fd, s)
    OSError: [Errno 32] Broken pipe
    

    >>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE)
    >>> out,err = p.communicate()
    >>> print out
    [error from myapp regarding lack of input]
    

    知道我错过了什么吗?

    1 回复  |  直到 16 年前
        1
  •  3
  •   Alex Martelli    16 年前

    您的观察结果表明,myapp在未读取(所有)输入的情况下终止。对MyAPP一无所知,这很难证实,但是考虑一下

    $ echo 'hello world' | tr 'l' 'L'
    heLLo worLd
    

    现在。。。:

    >>> cmd = ['/usr/bin/tr']
    >>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE)
    >>> out,err = p.communicate('hello world')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/lib/python2.5/subprocess.py", line 668, in communicate
        return self._communicate(input)
      File "/usr/lib/python2.5/subprocess.py", line 1218, in _communicate
        bytes_written = self._write_no_intr(self.stdin.fileno(), buffer(input, input_offset, 512))
      File "/usr/lib/python2.5/subprocess.py", line 997, in _write_no_intr
        return os.write(fd, s)
    OSError: [Errno 32] Broken pipe
    

    因为…:

    >>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
    >>> /usr/bin/tr: missing operand
    Try `/usr/bin/tr --help' for more information.
    

    如果我们修复了错误:

    >>> cmd = ['/usr/bin/tr', 'l', 'L']
    >>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
    >>> out,err = p.communicate('hello world')>>> print out
    heLLo worLd
    >>> print err
    None
    

    …它可以修复一切。如果省略了stderr重定向,会发生什么?您是否可能看到来自myapp的任何错误消息。。。?