【问题标题】:Broken Pipe from subprocess.Popen.communciate() with stdin带有标准输入的 subprocess.Popen.communicate() 的管道损坏
【发布时间】:2011-01-05 06:54:13
【问题描述】:

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

$ echo "输入文本" | /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('输入文本') 回溯(最近一次通话最后): 文件“”,第 1 行,在 文件“/usr/lib/python2.5/subprocess.py”,第 670 行,在通信中 返回self._communicate(输入) _communicate 中的文件“/usr/lib/python2.5/subprocess.py”,第 1223 行 bytes_written = self._write_no_intr(self.stdin.fileno(), buffer(input, input_offset, 512)) _write_no_intr 中的文件“/usr/lib/python2.5/subprocess.py”,第 1003 行 返回 os.write(fd, s) OSError:[Errno 32] 损坏的管道

为了让事情变得更奇怪,如果我遗漏输入数据,我不会收到任何错误。但是,这并不是一个很好的解决方法,因为应用程序需要输入才能工作。

>>> p = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,stdin=subprocess.PIPE) >>> out,err = p.communicate() >>> 打印出来 [myapp 关于缺少输入的错误]

知道我错过了什么吗?

【问题讨论】:

    标签: python


    【解决方案1】:

    您的观察表明 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... 的任何错误消息?

    【讨论】:

    • 我可以在 2.6 上重现这个,但在 2.7 上没有足够大的输入(例如communicate('foo\n'*100000))。是否更改了通信()对 EPIPE 的处理?
    猜你喜欢
    • 2019-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-17
    • 1970-01-01
    • 2018-03-27
    • 1970-01-01
    相关资源
    最近更新 更多