从 c++ 中的 python 程序中检索 stderr
Retrieve stderr from a python program in a c++ one
我目前正在尝试使用 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();
有了这个,我的 QStringLists 中就有了所有输出!
我目前正在尝试使用 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();
有了这个,我的 QStringLists 中就有了所有输出!