如何在c ++代码中捕捉python stdout [英] How To catch python stdout in c++ code

查看:294
本文介绍了如何在c ++代码中捕捉python stdout的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个程序,在它运行时有时需要调用python以完成一些任务。我需要一个函数调用python和 catches pythons stdout 并把它放在一些文件。
这是函数的声明

  pythonCallBackFunc(const char * pythonInput)

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

  #includeboost\python.hpp
#include< iostream>

void pythonCallBackFunc(const char * inputStr){

PyRun_SimpleString(inputStr);
}


int main(){
...
// S0me外部函数这样做
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'));
...

//另一个函数代码
PyRun_SimpleString(sys.stdout = old_stdout);
PyRun_SimpleString(fsock.close());

Py_Finalize();
return 0;
}

有更好的方法吗?此外,由于某些原因,当PyRun_SimpleString获取一些数学表达式时,PyRun_SimpleString不会执行任何操作,例如PyRun_SimpleString(5 ** 3)什么也不打印(python conlsul打印结果:125)



也许这很重要,我使用visual studio 2008.
谢谢,
Alex






根据Mark的建议做出的更改:

  #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\\\
\
; //这是python代码重定向stdouts / stderr

PyObject * pModule = PyImport_AddModule(__ main__); // create main module
PyRun_SimpleString(stdOutErr.c_str()); //调用代码重定向

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

PyObject * output = PyObject_GetAttrString(catcher,value);
printf(这里是输出:%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后得到的输出:



这里是输出:123

下面是输出:
下面是输出:
这里是输出:2

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

 这里是输出:123 

这里是输出:6

这里是输出:
这里是输出:2



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



Thaks,
Alex

解决方案

如果我正确地读取你的问题,你想捕获stdout / stderr你可以通过重定向stdout / stderr到一个python变量,然后查询这个变量到你的C ++。请不要,我没有做适当的计数如下:

  #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\\\
\
; //这是python代码重定向stdouts / stderr

Py_Initialize();
PyObject * pModule = PyImport_AddModule(__ main__); // create main module
PyRun_SimpleString(stdOutErr.c_str()); //调用代码重定向
PyRun_SimpleString(print(1 + 1)); // this is ok stdout
PyRun_SimpleString(1 + a); // this creating a 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); //从我们的catchOutErr对象获取stdout和stderr

printf(这里是输出:\\\
%s,PyString_AsString(output)); //它不在我们的C ++部分

Py_Finalize();


return 0;

}


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)

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 "boost\python.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;
}

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)

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


Changes I've made according Mark's suggestion:

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

  using namespace std;

  void PythonPrinting(string inputStr){ 
     string stdOutErr =
    "import sys\n\
     class CatchOut:\n\
        def __init__(self):\n\
           self.value = ''\n\
        def write(self, txt):\n\
           self.value += txt\n\
     catchOut = CatchOut()\n\
     sys.stdout = catchOut\n\
     sys.stderr = catchOut\n\
    "; //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\n", 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;
  }

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

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?

Thaks, Alex

解决方案

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

    Py_Finalize();


    return 0;

}

这篇关于如何在c ++代码中捕捉python stdout的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆