python - 从 c++ 中的 python 程序中检索 stderr

标签 python c++ pipe stderr traceback

我目前正在尝试使用 pstream 库 ( http://pstreams.sourceforge.net/ ) 从我的 C++ 程序启动一个用 python 编写的文件。我的代码如下所示:

QStringList res;
QStringList resErrors;

// run a process and create a streambuf that reads its stdout and stderr
redi::pstream proc(cmd, redi::pstreams::pstdout | redi::pstreams::pstderr);

std::string line;
// read child's stdout
while (std::getline(proc.out(), line))
    res.append(QString::fromStdString(line));
// read child's stderr
while (std::getline(proc.err(), line))
    resErrors.append(QString::fromStdString(line));

通常我可以正确地接收到来自在 pstream 构造函数中输入的任何命令的 out 和 err 消息。但是如果我尝试执行一个引发回溯的 python 文件,我没有任何输出(在 stdout 或 stderr 中)。

例如,这个 python 文件:

#!/usr/bin/env python

test = 5 / 0
print "test"

不会在 stdout 中打印“test”,也不会在 stderr 中打印任何内容。但是如果我在终端中执行它,我会正确地得到:

Traceback (most recent call last):
   File "test.py", line 3, in <module>
       test = 5 / 0
   ZeroDivisionError: integer division or modulo by zero

在这两种情况下,我都使用了相同的命令:“python test.py”

我想我需要告诉 python 将其回溯打印到 stderr?但为什么不在子流程中完成呢?还是库中的错误?

我想到的另一种可能性是我过早地读取了标准输出和标准错误,而 Python 没有时间写入其中。但是我试过在读取之前加一个sleep函数,没有任何效果。

最佳答案

好的,@Jean-François Fabre 的部分答案有效地解决了这个问题。

我注意到 pstreams 提供了一种在管道上读取而不阻塞的方法,所以我重用了该代码(在库的文档中找到):

const redi::pstreams::pmode mode = redi::pstreams::pstdout|redi::pstreams::pstderr;
redi::ipstream child(cmd, mode);
char buf[1024];
std::streamsize n;
bool finished[2] = { false, false };
while (!finished[0] || !finished[1])
{
    if (!finished[0])
    {
        while ((n = child.err().readsome(buf, sizeof(buf))) > 0) {
            std::string ret(buf, n);
            resErrors.append(QString::fromStdString(ret));
        }
        if (child.eof())
        {
            finished[0] = true;
            if (!finished[1])
                child.clear();
        }
    }

    if (!finished[1])
    {
        while ((n = child.out().readsome(buf, sizeof(buf))) > 0) {
            std::string out(buf, n);
            res.append(QString::fromStdString(out));
        }
        if (child.eof())
        {
            finished[1] = true;
            if (!finished[0])
                child.clear();
        }
    }
}
res = res.join("").split("\n");
resErrors = resErrors.join("").split("\n");
res.removeLast();
resErrors.removeLast();

有了这个,我的 QStringList 中就有了所有输出!

关于python - 从 c++ 中的 python 程序中检索 stderr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47907555/

相关文章:

python - 无法在 MacOS 上安装 pyicu

C++ 预处理器测试类成员是否存在

c++ - 前向声明的单例类,带有来自具有前向声明的类的友元函数

unix - Grep:递归选项在输入管道输入时会产生意外行为

c - sem_open 不适用于 Ubuntu : undefined reference to `sem_open'

python - 将卷积操作应用于图像 - PyTorch

python - 如何在 cython 的结构中使用文件指针

python - 使用 Psycopg2 从 Redshift 写入文件抛出异常

c++ - 我可以动态更改在 Visual Studio 中使用 C++ 创建的对话框窗口的字体大小吗?

android - 如何使管道符号或 Grep 在 Android 进程运行时命令中工作?