如何在 C++ 代码中捕获 Python 3 stdout

How to catch Python 3 stdout in C++ code

old question about how to catch python stdout in C++ code, there is a good answer 中有效 - 但仅在 Python 中有效 2.

我想在 Python 中使用类似的东西 3. 有人可以帮我吗?

更新

我使用的代码如下。它是从上面引用的 Mark answer 移植过来的,唯一的变化是使用 PyBytes_AsString 而不是 PyString_AsString,如 cited in documentation.

#include <Python.h>
#include <string>

int main(int argc, char** argv)
{
std::string stdOutErr =
"import sys\n\
class CatchOutErr:\n\
    def __init__(self):\n\
        self.value = ''\n\
    def write(self, txt):\n\
        self.value += txt\n\
catchOutErr = CatchOutErr()\n\
sys.stdout = catchOutErr\n\
sys.stderr = catchOutErr\n\
"; //this is python code to redirect stdouts/stderr

Py_Initialize();
PyObject *pModule = PyImport_AddModule("__main__"); //create main module
PyRun_SimpleString(stdOutErr.c_str()); //invoke code to redirect
PyRun_SimpleString("print(1+1)"); //this is ok stdout
PyRun_SimpleString("1+a"); //this creates an error
PyObject *catcher = PyObject_GetAttrString(pModule,"catchOutErr"); //get our catchOutErr created above
PyErr_Print(); //make python print any errors

PyObject *output = PyObject_GetAttrString(catcher,"value"); //get the stdout and stderr from our catchOutErr object

printf("Here's the output:\n %s", PyBytes_AsString(output)); //it's not in our C++ portion

Py_Finalize();


return 0;
}

我使用 Python 3 库构建它:

g++ -I/usr/include/python3.6m -Wall -Werror -fpic code.cpp -lpython3.6m

输出为:

Here's the output: (null)

如果有人需要有关该问题的更多信息,请告诉我,我会尽量在此处提供。

您的问题是 .value 不是 bytes 对象,它是 string(即 Python2 unicode)对象。因此 PyBytes_AsString 失败。我们可以使用 PyUnicode_AsEncodedString.

将其转换为 bytes 对象
PyObject *output = PyObject_GetAttrString(catcher,"value"); //get the stdout and stderr from our catchOutErr
PyObject* encoded = PyUnicode_AsEncodedString(output,"utf-8","strict");
printf("Here's the output:\n %s", PyBytes_AsString(encoded));

请注意,您应该对照 NULL 检查这些结果 PyObject* 以查看是否发生了错误。