从python解释器调用方法

时间:2011-08-12 00:05:52

标签: c++ python

根据Voo对此主题的建议:

How can I "hook into" Python from C++ when it executes a function? My goal is to profile

我为一个新问题开辟了一个新线程,在C ++中,我如何初始化PythonInterpreter然后从中调用一个方法。具体来说,我希望能够调用cProfile的方法并从中获取数据。

1 个答案:

答案 0 :(得分:0)

好的,这会有点长。请注意,我几乎忽略了所有“常规”错误检查 - 几乎任何python方法都可能返回NULL,在这种情况下你应该优雅地处理它。我显示“异常”部分检查给定对象是否可调用。请注意,如果对象指针为NULL,PyDECREF将失败,而Py_XDECREF则不会。现在代码 - 可能有更好的方法来解决所有这些,但这对我来说很好,遗憾的是文档非常缺乏。

C ++代码:

#include <Python.h>

static PyThreadState *mainstate;

void initPython(){
    PyEval_InitThreads();
    Py_Initialize();
    mainstate = PyThreadState_Swap(NULL);
    PyEval_ReleaseLock();
}

void exitPython(){
    PyEval_AcquireLock();
    PyThreadState_Swap(mainstate);
    Py_Finalize(); 
}

void callScript() {
    PyGILState_STATE gstate = PyGILState_Ensure();
    PyObject *pName = PyUnicode_FromString("Startup"); 
    PyObject *pModule = PyImport_Import(pName);
    Py_DECREF(pName);
    PyObject *pFunc = PyObject_GetAttrString(pModule, "startup");
    if (pFunc && PyCallable_Check(pFunc)) {
        PyObject *arglist = Py_BuildValue("(u)", "TestScript");
        PyObject *result = PyObject_CallObject(pFunc, arglist);
        Py_DECREF(arglist);
        // Now you have the returned object of the function - do something with it.
        // In our case that's None, but you should extend the python scrip to return
        // whatever you need - see the profiler API.
        Py_DECREF(result);          
    }
    Py_XDECREF(pFunc);  // XDECREF does not fail if pointer is NULL.
    Py_DECREF(pModule);
    PyGILState_Release(gstate); 
}

int main() {
    printf("Start.\n");
    initPython();
    callScript();
    exitPython();
    printf("Exit.\n");
    return 0;
}

总是调用您的特定脚本,对其进行更改,以便以有用的方式返回所需的所有数据 - 目前我们只使用cProfile.run()打印一些信息:

Startup.py
import cProfile

def startup(module_name):
    print("Start script")
    cProfile.run("import " + module_name)
    print("Finished script")

最后执行的简单脚本:

TestScript.py
sum = 0
for i in range(10000):
    sum += i