Python子进程包返回折断的管道

时间:2019-01-14 18:40:05

标签: python python-3.x subprocess

我正在尝试做一个使用子流程包的非常简单的示例。 python脚本应打开一个新进程并运行read命令。 read命令应通过PIPE接收来自stdin的输入。每当我尝试使用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

注意:一个字符接一个字符发送(睡眠超时)非常重要。

1 个答案:

答案 0 :(得分:1)

我实际上无法复制您的结果*,在我的情况下,您的循环运行了,由于assert尚未完成并且还没有p({或当时的值仍为returncode)。在循环之后和None之前插入p.wait()将迫使我们仅在assert终止之后检查结果。

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


*在我的系统上,returncode/bin/sh一起使用的subprocess.Popen()实际上是shell=True。运行bash(大概是您系统上的["/bin/dash", "-c", "read"]的shell调用),我也遇到了断线的情况。


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

  

/bin/sh

并返回/bin/dash: 1: read: arg count

哪种方式使问题更加棘手:为什么调用2(从/bin/dash -c "read")失败。似乎破折号python(不同于其bash副本)总是期望至少有一个变量名作为参数读入(用read代替read)。


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