【问题标题】:Python subprocess module does not return stdout on segfaultPython 子进程模块在段错误时不返回标准输出
【发布时间】:2012-05-21 13:36:28
【问题描述】:

我正在从 Python 运行一个 C 可执行文件,这个可执行文件有时会出现段错误。当它发生段错误时,子进程模块不会在 stdout 或 stderr 中返回任何内容。

示例代码:

import subprocess

proc = subprocess.Popen(['./a.out'], stdin=subprocess.PIPE,
        stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate()
print 'out: "%s"' % out
print 'err: "%s"' % err
print proc.returncode

a.out的来源是:

int main() {
    printf("hello world\n");
    int x = 1 / 0;
}

./a.out 的输出为:

hello world
Floating point exception

Python 代码的输出是(在 Linux 中,python 2.7):

out: ""
err: ""
-8

有没有办法在可执行文件崩溃的情况下获取它的输出?

将返回码转换为字符串消息的通用方法也不错。

【问题讨论】:

    标签: python segmentation-fault subprocess


    【解决方案1】:

    应用程序几乎可以肯定在遇到分段错误之前不会刷新其输出缓冲区。

    默认情况下,C stdio 库为stdout 配置缓冲,以便在行的每一端刷新缓冲区,但只有stdout 是一个tty。这就是为什么当您从命令行运行 a.out确实会看到输出。

    你不能直接让 C 程序从 Python 端改变它。但是你可以做的是给它一个tty来使用它的stdout,也就是一个伪tty。打开和设置伪终端的细节比设置常规管道要复杂得多,但有一些模块可以帮助您:请参阅 Pexpectthis SO question 等。

    【讨论】:

      【解决方案2】:

      您的 C 程序没有刷新其输出缓冲区。解决此问题的最简单方法是将 STDOUT 的输出模式更改为无缓冲:

      #include <stdio.h>
      int main(int argc,char **argv) {
          setvbuf(stdout,_IONBF,0,0);
          printf("hello world\n");
          int x = 1 / 0;
      }
      

      现在您的程序(我对其进行了编辑以修复错字)产生了正确的输出:

      $ python2.7 x.py
      out: "hello world
      "
      err: ""
      0
      $
      

      在我的 Mac 上返回码是 0,令人困惑,因为因信号而终止的程序没有返回码。

      【讨论】:

      • 很好的解决方案,如果您控制 C 代码并且能够将 setvbuf 调用添加到其中并重新编译。我假设第三方 C 代码无法修改。
      • 好吧,如果您的第三方代码在崩溃之前没有刷新其标准输出,那么您无能为力。
      猜你喜欢
      • 2010-11-19
      • 2015-09-25
      • 1970-01-01
      • 2011-05-19
      • 2011-08-29
      • 2015-01-20
      • 1970-01-01
      • 2012-09-17
      • 2018-05-27
      相关资源
      最近更新 更多