Importing Python module in C++ not in main.

huangapple go评论65阅读模式
英文:

Importing Python module in C++ not in main

问题

以下是翻译好的部分:

"我想在C++中使用Python模块。在我找到的所有示例中,它们在main函数内执行诸如Py_Initialize()Py_FinalizeEx()之类的操作,还有其他一些操作。然而,在我的应用程序中,我只是在编写一个较大系统的一小部分,无法访问main函数。我只是在编写一个将在程序的某个地方多次调用的函数。在这种情况下,如何进行Python部分的初始化和最终化呢?我猜我可以在我的函数内部完成所有操作,但是每次调用函数时都进行解释器初始化、导入等操作可能会变得非常慢。我在C++方面经验有限,不确定是否可以实现类似以下伪代码的方式:"

Edit 1

"伪代码:"

#include <Python.h>

class MyPackage:
  def constructor:
    Py_Initialize();
    self.module = load_python_module();
    // 在这里执行与初始化相关的其他操作。
  
  def destructor:
    Py_FinalizeEx();

package = MyPackage(); // 这现在是全局的

void my_func(void) {
  blah();
  package.whatever();
}

请注意,由于您要求只返回翻译的部分,我只提供了上述部分的翻译。如果您需要更多帮助,请告诉我。

英文:

I want to use a Python module within C++. In all examples I find (doc, SO1, SO2) they do things like Py_Initialize() and Py_FinalizeEx(), among other things, within the main function. In my application, however, I am writing a small part of a larger system and have no access to main. I am just writing a function that will be called many times somewhere in the program. What would be the way of doing all the initialization and finalization of the Python stuff in this case? I guess I could do everything within my function, but initializing the interpreter, importing, etc. every time the function is called will probably become very slow. I am not very experienced in C++, not sure if something like the following pseudocode is possible:

void my_func(void) {
  if (my_func_is_called_for_the_first_time()) {
    Py_Initialize();
    module = load_python_module();
    etc_related_to_init_stuff();
  }
  if (exiting_program()) { // Don&#39;t know how this would work, but you get the idea... Something like the `atexit` functionality from Python.
    clean_everything_related_to_python_and_the_module();
    Py_FinalizeEx();
  }
  // Actual code of my function using the package goes here...
}

Edit 1

Pseudocode:

#include &lt;Python.h&gt;

class MyPackage:
  def constructor:
    Py_Initialize();
    self.module = load_python_module();
    // Do other things related to the initialization here.
  
  def destructor:
    Py_FinalizeEx();

package = MyPackage(); // This is now global

void my_func(void) {
  blah();
  package.whatever();
}

答案1

得分: 2

这是使用 static 局部变量的完美用例:

struct PythonInitializer
{
    PyObject* module;
    PythonInitializer()
    {
        Py_Initialize();
        module = load_python_module();
    }

    ~PythonInitializer()
    {
        clean_everything_related_to_python_and_the_module();
        Py_FinalizeEx();
    }
};

void my_func()
{
    static PythonInitializer python;

    // 使用 python.module
}

这里的技巧是,static 局部变量在首次调用函数时构造,它们的生命周期延伸到程序的结束。因此,在首次调用 my_func 时将构造一个 PythonInitializer 对象,它将初始化Python解释器。PythonInitializer 的析构函数将在程序正常退出时被调用,从而清理Python解释器。


请注意,这在程序中与Python的其他用户不兼容。如果另一个函数调用了 Py_FinalizeEx,那么解释器将在你的代码下被卸载。如果在你的应用程序中有其他Python用户,你应该在函数中添加一个 Py_IsInitialized() 检查,以便在其他人卸载它时重新加载Python,或者将初始化和清理移动到其他地方。

英文:

This is the perfect use-case for a static local variable:

struct PythonInitializer
{
    PyObject* module;
    PythonInitializer()
    {
        Py_Initialize();
        module = load_python_module();
    }

    ~PythonInitializer()
    {
        clean_everything_related_to_python_and_the_module();
        Py_FinalizeEx();
    }
};

void my_func()
{
    static PythonInitializer python;

    // use python.module
}

The trick here is that static local variables are constructed the first time a function is called and their lifetime extends to the end of the program. So a PythonInitizlizer object will be constructed the first time my_func is called, which will initialize the python interpreter. The PythonInitilizer's destructor will get called when the program exits (cleanly) and clean up the python interpreter.


Note that this will not play well with other users of python in your program. If another function calls Py_FinalizeEx then the interpreter will get unloaded out from under you. If there are other users of python in your application you should add a Py_IsInitialized() check to your function to re-load python if someone else unloads it or move initialization and cleanup somewhere else.

huangapple
  • 本文由 发表于 2023年4月13日 23:29:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76007256.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定