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

问题描述 投票:2回答:1

我目前正在尝试使用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构造函数中输入的任何命令接收和错误消息。但是如果我尝试执行一个引发回溯的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?但为什么不在子进程中完成呢?或者它可能是图书馆中的错误?

我想到的另一种可能性是我太早读了stdout和stderr而python没有时间写它。但我在尝试之前尝试添加睡眠功能,没有任何影响。

python c++ pipe stderr traceback
1个回答
1
投票

好吧,这个问题可以通过@ Jean-FrançoisFabre的部分答案得到有效解决。

我注意到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();

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

© www.soinside.com 2019 - 2024. All rights reserved.