简体   繁体   English

从 python 解释器调用方法

[英]calling a method from a python interpreter

per Voo's advice on this thread:根据 Voo 对此线程的建议:

How can I "hook into" Python from C++ when it executes a function? 当它执行 function 时,如何从 C++ “挂钩” Python? My goal is to profile 我的目标是简介

I have opened up a new thread for a new question, which is, in C++, how can I initialize a PythonInterpreter and then call a method from it.我为一个新问题开辟了一个新线程,即在 C++ 中,如何初始化 PythonInterpreter,然后从中调用方法。 Specifically, I'd like to be able to call cProfile's methods and also get data from it.具体来说,我希望能够调用 cProfile 的方法并从中获取数据。

Okay that'll be a bit longer.好的,那会更长一点。 Note that I pretty much ignore all "usual" error checking - pretty much any python method may return NULL in which case you should handle that gracefully.请注意,我几乎忽略了所有“常规”错误检查 - 几乎任何 python 方法都可能返回 NULL 在这种情况下您应该优雅地处理它。 I show the "unusual" part checking if the given object is callable.我展示了“不寻常”部分,检查给定的 object 是否可调用。 Note that PyDECREF fails if the object pointer is NULL, Py_XDECREF does not.请注意,如果 object 指针为 NULL,则 PyDECREF 会失败,而 Py_XDECREF 不会。 And now to the code - there may be a better way to solve all this, but this works fine for me and sadly the documentation is extremely lacking.现在到代码 - 可能有更好的方法来解决所有这些问题,但这对我来说很好,遗憾的是文档非常缺乏。

C++ code: 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;
}

Your specific script that is always called, change this so that you return all the data you want in a useful manner - at the moment we just use cProfile.run() which just prints some information:始终调用您的特定脚本,更改它以便您以有用的方式返回所需的所有数据 - 目前我们只使用 cProfile.run() ,它只打印一些信息:

Startup.py
import cProfile

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

Finally the trivial script that is executed:最后执行的简单脚本:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM