【问题标题】:Python subprocess package returns broken pipePython 子进程包返回损坏的管道
【发布时间】:2019-01-14 18:40:04
【问题描述】:

我正在尝试做一个使用 subprocess 包的非常简单的示例。 python 脚本应该打开一个新进程并运行read 命令。 read 命令应该通过 PIPE 从标准输入接收输入。每次我尝试使用 write()flush() 时,它都会说:

Traceback (most recent call last):
  File "recorder.py", line 68, in <module>
    p.stdin.flush()
BrokenPipeError: [Errno 32] Broken pipe

我的python代码如下:

import subprocess
import time


p = subprocess.Popen(
    [
        "read",
    ],
    stdout=subprocess.PIPE,
    stdin=subprocess.PIPE,
    stderr=subprocess.STDOUT,
    shell=True,
    bufsize=1
)

for character in "This is the message!\n":
    p.stdin.write(character.encode("utf-8"))
    time.sleep(0.25)
    p.stdin.flush()

assert p.returncode == 0

注意:逐个字符发送一个字符(带有休眠超时)非常重要。

【问题讨论】:

    标签: python python-3.x subprocess


    【解决方案1】:

    我实际上无法复制您的结果*,在我的情况下,您的循环运行并在assert 上失败,因为p 尚未完成并且没有returncode(或者更确切地说它的值仍然是None 当时)。在循环之后和assert 之前插入p.wait() 将强制我们仅在p 终止后检查结果。

    现在对于您看到的异常,它很可能表明您尝试在flush() 上执行的管道已关闭。很可能是由于进程已经终止。也许在你的情况下,它已经有一个(非零)returncode,这可以进一步帮助理解这个问题?**


    * 在我的系统上,subprocess.Popen()shell=True 使用的/bin/sh 实际上是bash。在您的系统上运行["/bin/dash", "-c", "read"] 可能恰好是调用/bin/sh 的shell,我的管道也损坏了。


    ** 像这样运行破折号似乎失败了:

    /bin/dash: 1: read: arg count

    然后返回2

    这更像是一个破折号的问题:为什么调用/bin/dash -c "read"(来自python)会失败。似乎破折号read(与其对应的bash 不同)总是希望至少有一个变量名作为参数读入(将read 替换为read foo)。


    我猜这个 python 问题只是成为关于假设和 shell 脚本可移植性的一课。 :)

    【讨论】: