如何在c ++中存储多个单独的python会话并与之交互?

时间:2016-06-14 13:31:31

标签: python c++

在我的c ++程序中,我有一个名为“pEngine”的类,它应该处理我的程序和python会话之间的交互。可以有任意数量的这些pEngine,每个都需要单独工作,因为在初始化期间它们每个都执行不同的python脚本(直到运行时才知道)。

目前我有每个脚本定义一个主函数,它接受一个变量,有效负载,并根据脚本产生一个不同的输出,我的程序管道返回。然后删除pEngine。对于单个pEngine,我的代码工作得很好,允许我在函数的脚本中预加载数据,然后在需要时调用它。

我的问题是,由于它关闭了会话,所有其他pEngine都会受到影响。我无法将多个脚本加载到同一个会话中,因为它们的主要功能都有相同的原型。我正在寻找的是一种方法,让python会话实例对象是独立的和个体的,所以我可以对它运行命令。

我的pEngine.h

#include <cstring>
#include "Engine.h"
#include "/usr/include/python2.7/Python.h"

#ifndef PENGINE_H
#define PENGINE_H

class pEngine : public Engine
{
public:
    pEngine();
    ~pEngine();

    std::string execute(const std::string& cmd);         
    int setwd(const std::string& dir);
    int source(const std::string& script);

    std::string main(const std::string& payload);
private:
        PyObject *pModule;
        PyObject *stdOut;
};

#endif /* PENGINE_H */

我的pEngine.cpp

#include "pEngine.h"

pEngine::pEngine()
{
    /* Start a python session and create a class to capture the standard out 
     text. Define it as the standard out location and run this code in the 
     session. Then store a pointer to this python object to extract returned
     values. */
    Py_Initialize();
    pModule = PyImport_AddModule("__main__"); //create main module
    std::stringstream pythonOutputs;
    pythonOutputs << "import sys" << "\n"
                  << "class CatchStdOut:" << "\n"
                  << "\t" << "def __init__(self):" << "\n"
                  << "\t" << "\t" << "self.value = ''" << "\n"
                  << "\t" << "def write(self, txt):" << "\n"
                  << "\t" << "\t" << "self.value += txt" << "\n"
                  << "\t" << "def clear(self):" << "\n"
                  << "\t" << "\t" << "self.value = ''" << "\n"
                  << "StdOut = CatchStdOut()" << "\n"
                  << "sys.stdout = StdOut";
    PyRun_SimpleString((pythonOutputs.str()).c_str());
    stdOut = PyObject_GetAttrString(pModule,"StdOut");
}

pEngine::~pEngine(){
    Py_Finalize();
}

std::string pEngine::execute(const std::string& cmd)
{   
    /* Place cmd in try except statement to protect against unknown errors. */
    std::stringstream pString;
    pString << "program_status = 200" << "\n"
            << "StdOut.clear()" << "\n"
            << "try:" << "\n"
            << "\t" << cmd << "\n"
            << "except Exception as e:" << "\n"
            << "\t" << "program_status = 400" << "\n"
            << "\t" << "print(e)";

    /* Run Command against the interpreter and store returned answer. */
    PyRun_SimpleString( (pString.str()).c_str() );
    PyErr_Print(); //make python print

    //returned payload
    std::string RPL = 
        PyString_AsString(PyObject_GetAttrString(stdOut,"value"));


    /* Clear the payload from the capture object and run a command to fill in
     the status. */
    std::stringstream statusCollector;
    statusCollector << "StdOut.clear()\n"
                    << "print program_status";

    /* Run command and extract status. */
    PyRun_SimpleString( (statusCollector.str()).c_str() );
    PyErr_Print();

    //status
    std::string PST = 
        PyString_AsString(PyObject_GetAttrString(stdOut,"value"));

    if (!RPL.empty() && RPL[RPL.length()-1] == '\n') RPL.erase(RPL.length()-1);
    if (!PST.empty() && PST[PST.length()-1] == '\n') PST.erase(PST.length()-1);

    /* Set Program status and return the payload from the python session. */
    program_status = std::stoi( PST );
    return RPL;
}

std::string pEngine::main(const std::string& payload)
{
    std::string returned = execute( "print main("+toEscapedString(payload)+")");
    Py_Finalize();
    if( program_status != 200 ) status = Engine::ENG_EXECUTE_ERROR;
    return returned;
}

int pEngine::setwd(const std::string& dir)
{
    std::string pString = "import os\n\tos.chdir(" + toEscapedString(dir) + ")";
    execute( pString );
    if( program_status != 200 ) status = Engine::ENG_SESSION_ERROR;
    return status;
}

int pEngine::source(const std::string& script)
{    
    std::string pString = "execfile(" + toEscapedString(script) + ")";
    execute( pString );
    if( program_status != 200 ) status = Engine::ENG_SESSION_ERROR;
    return status;
}

0 个答案:

没有答案