如何在 C++ 代码中捕获 python 标准输出

我有一个程序,它在运行期间有时需要调用 python 来执行某些任务.我需要一个函数来调用 python 并捕获 python 标准输出并将其放入某个文件中.这是函数的声明

I have a program which during it's run sometimes needs to call python in order to preform some tasks. I need a function that calls python and catches pythons stdout and puts it in some file. This is a declaration of the function

  pythonCallBackFunc(const char* pythonInput)

我的问题是捕获给定命令的所有 python 输出 (pythonInput).我没有使用 python API 的经验,我不知道什么是正确的技术来做到这一点.我尝试的第一件事是使用 Py_run_SimpleString 重定向 python 的 sdtout 和 stderr这是我编写的代码的一些示例.

My problem is to catch all the python output for a given command (pythonInput). I have no experience with python API and I don't know what is the right technique to do this. First thing I've tried is to redirect python's sdtout and stderr using Py_run_SimpleString this is some example of the code i've written.

#include "boostpython.hpp"
#include <iostream>

void pythonCallBackFunc(const char* inputStr){   

    PyRun_SimpleString(inputStr); 
}


int main () {
    ...
   //S0me outside functions does this
   Py_Initialize();
   PyRun_SimpleString("import sys");
   PyRun_SimpleString("old_stdout = sys.stdout");
   PyRun_SimpleString("fsock = open('python_out.log','a')");
   PyRun_SimpleString("sys.stdout = fsock");
   ...

   //my func   
   pythonCallBackFunc("print 'HAHAHAHAHA'");
   pythonCallBackFunc("result = 5");
   pythonCallBackFunc("print result");

   pythonCallBackFunc("result = 'Hello '+'World!'");
   pythonCallBackFunc("print result");

   pythonCallBackFunc("'KUKU '+'KAKA'");
   pythonCallBackFunc("5**3");

   pythonCallBackFunc("prinhghult");

   pythonCallBackFunc("execfile('stdout_close.py')");
   ... 

   //Again anothers function code
   PyRun_SimpleString("sys.stdout = old_stdout");
   PyRun_SimpleString("fsock.close()");

   Py_Finalize();
   return 0;
}

有没有更好的方法来做到这一点?此外,由于某些原因,PyRun_SimpleString 在得到一些数学表达式时什么也不做,例如 PyRun_SimpleString("5**3") 什么都不打印(python conlsul 打印结果:125)

Is there a better way to do this? Besides, for some reason PyRun_SimpleString does nothing when it gets some mathematical expression, for example PyRun_SimpleString("5**3") prints nothing (python conlsul prints the result: 125)

也许这很重要,我正在使用 Visual Studio 2008.谢谢,亚历克斯

maybe it is important, i am using visual studio 2008. Thanks, Alex

我根据 Mark 的建议所做的更改:

Changes I've made according Mark's suggestion:

  #include <python.h>
  #include <string>

  using namespace std;

  void PythonPrinting(string inputStr){ 
     string stdOutErr =
    "import sys

     class CatchOut:

        def __init__(self):

           self.value = ''

        def write(self, txt):

           self.value += txt

     catchOut = CatchOut()

     sys.stdout = catchOut

     sys.stderr = catchOut

    "; //this is python code to redirect stdouts/stderr

     PyObject *pModule = PyImport_AddModule("__main__"); //create main module
     PyRun_SimpleString(stdOutErr.c_str()); //invoke code to redirect

     PyRun_SimpleString(inputStr.c_str());
     PyObject *catcher = PyObject_GetAttrString(pModule,"catchOut");

     PyObject *output = PyObject_GetAttrString(catcher,"value");
     printf("Here's the output: %s
", PyString_AsString(output)); 
     }

  int main(int argc, char** argv){
         Py_Initialize();

     PythonPrinting("print 123");
     PythonPrinting("1+5");
     PythonPrinting("result = 2");
         PythonPrinting("print result");

         Py_Finalize();
         return 0;
  }

运行 main 后得到的输出:

The output i get after running main:

 Here's the output: 123

 Here's the output:
 Here's the output: 
 Here's the output: 2

这对我有好处,但只有一个问题,应该是

It is good for me , but only one problem, it should be

 Here's the output: 123

 Here's the output: 6

 Here's the output: 
 Here's the output: 2

我不知道为什么但是在运行这个命令之后:PythonPrinting("1+5"), PyString_AsString(output) 命令返回一个空字符串 (char*) 而不是 6... :( 有什么我不能做的吗?松开这个输出?

I dont know why but after running this command: PythonPrinting("1+5"), PyString_AsString(output) command returns an empty string (char*) instead of 6... :( Is there somthing i can do not to loose this output?

谢谢,亚历克斯

推荐答案

如果我正确阅读了您的问题,您想将 stdout/stderr 捕获到 C++ 中的变量中吗?您可以通过将 stdout/stderr 重定向到一个 python 变量,然后将该变量查询到您的 C++ 中来做到这一点.请注意,我没有在下面进行正确的引用计数:

If I'm reading your question correctly, you want to capture stdout/stderr into a variable within your C++? You can do this by redirecting stdout/stderr into a python variable and then querying this variable into your C++. Please not that I have not done the proper ref counting below:

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

int main(int argc, char** argv)
{
    std::string stdOutErr =
"import sys

class CatchOutErr:

    def __init__(self):

        self.value = ''

    def write(self, txt):

        self.value += txt

catchOutErr = CatchOutErr()

sys.stdout = catchOutErr

sys.stderr = catchOutErr

"; //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:
 %s", PyString_AsString(output)); //it's not in our C++ portion

    Py_Finalize();


    return 0;

}

相关文章