【问题标题】:Python subprocess.Popen stdin interfering with stdout/stderrPython subprocess.Popen 标准输入干扰标准输出/标准错误
【发布时间】:2011-11-30 03:04:48
【问题描述】:

对此感到非常困惑。使用 Popen 时,如果仅使用 stdout 或 stderr,则以下代码有效:

def run(self):
    self.externalProcess = subprocess.Popen(['./external_process.out 1>&2'], shell=True, stderr=subprocess.PIPE)
    while self.externalBinary.poll() is None:
        print('Still running')
    print('Done running')

我正在使用 stderr 文件描述符,因为我正在 GUI 中实时监控进程输出,并且 stderr 没有缓冲。有关该混乱的更多背景信息,请参阅我的另一个问题: Python capture stdout from subprocess line by line

我在这里遇到的问题是,一旦我添加标准输入以允许将用户输入传递给外部进程,它就开始像标准输出再次缓冲一样:

def run(self):
    self.externalProcess = subprocess.Popen(['./external_process.out 1>&2'], shell=True, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
    while self.externalBinary.poll() is None:
        print('Still running')
    print('Done running')

我的问题是为什么 stdin 似乎会影响 stdout 和 stderr?

【问题讨论】:

  • 您的问题的具体症状是什么?不应该被阻止的东西?
  • 另外,工作代码将不胜感激 - 您的示例不会按书面方式运行。例如,stdout=STDERR 是什么?
  • 是的,我注意到没有 subprocess.STDERR 这样的东西。现在应该修好了。症状是我的 wxPython 应用程序中有一个文本框,一次显示一行输出。当我添加 stdin 参数时,它只显示几行停止。当我删除它时,它会继续显示我的外部进程的输出,这是一个 C 程序。
  • 您实际上在哪里向子进程发送输入?我没有看到在你的第二个例子中发生这种情况......
  • 我没有包含它,因为我一添加参数就看到了问题。我什至不需要尝试使用标准输入。阅读下面的链接后,我认为我的问题是由于缓存而死锁,所以我正在努力解决这个问题。在我关闭子进程之前,我不需要使用标准输入(我只是发送一个换行符来模拟按下的回车键,这是该程序干净退出的方式)。

标签: python subprocess popen


【解决方案1】:

您似乎正在尝试将数据写入子进程(通过 STDIN)并以交互方式读取其输出(通过 STDOUT)。

正如this SO question 的回答中提到的那样,这是不行的!

您可以使用Popen.communicate,但这是一个阻塞调用,它将等待所有通信完成(您不能像在示例中那样进行轮询)

【讨论】:

  • 良好的链接。我以前不明白死锁问题。我正在尝试让通信正常工作,但目前还没有。请参阅我上面的评论。
  • @tanders12:communicate() 有什么问题?
  • communicate() 似乎会缓冲所有内容,直到孩子退出。我需要它行缓冲或无缓冲。我正在尝试在不更改子代码的情况下完成此操作。现在我正在尝试让 pexpect 工作,它看起来很有希望。