【问题标题】:Segmentation fault occurs when PyRun_SimpleFile is called repeatedly重复调用 PyRun_SimpleFile 时出现分段错误
【发布时间】:2019-06-17 13:45:58
【问题描述】:

我想在 c++ 中嵌入用 3.5 版编写的 python 代码。此外,python 脚本需要作为整个脚本重复执行。我的代码如下。它在第一次迭代时执行良好,在第二次迭代时出现分段错误。

main.cpp:

#include <Python.h>
#include<iostream>
using namespace std;

int main(int argc, char *argv[])
{
    int i = 0;
    while(i<3){
    cout<<"start"<<endl;
    Py_Initialize();
    FILE* file;
    wchar_t* _argv[argc];
    for(int i=0; i<argc; i++){
        wchar_t *arg = Py_DecodeLocale(argv[i], NULL);
        _argv[i] = arg;
    }

    PySys_SetArgv(argc, _argv);
    PyObject *sys = PyImport_ImportModule("sys");
    PyObject *path = PyObject_GetAttrString(sys, "path");

    PyList_Append(path, PyUnicode_FromString("."));
    file = fopen("./example.py","r");
    PyRun_SimpleFile(file, "./example.py");
    fclose(file);
    Py_Finalize();
    cout<<"Done"<<endl;
    i++;
    }
    return 0;
}

example.py:

import tensorflow as tf

flags = tf.app.flags
FLAGS = flags.FLAGS

flags.DEFINE_float('learning_rate', 0.01, 'initial learning rate')

def main(argv=None):
    print(FLAGS.learning_rate)

if __name__ == '__main__':
    main()

我使用以下方法构建项目: cmake --build . --target Demo -- -j 2 并执行为: ./Demo --learning_rate 0.02

输出是:

start
0.02
Done
start
Segmentation fault (core dumped)

然后我将“example.py”的内容替换为: print("Hi")

输出是:

start
Hi
Done
start
Hi
Done
start
Hi
Done

如何解决上述分段错误?

【问题讨论】:

  • 您正在泄漏内存。虽然不是段错误的原因
  • 每次迭代都不需要初始化和完成python解释器
  • 如果我在循环之外进行初始化和完成,我会收到以下错误:absl.flags._exceptions.DuplicateFlagError:标志“learning_rate”被定义了两次。第一个来自 ./Demo,第二个来自 ./Demo。首次出现的描述:初始学习率
  • 您还应该在调用Py_Initialize 之前使用Py_SetPath,而不是导入sys 并更改path。这是正确的方法(只要在运行时不需要更改)。无论如何,很难判断出了什么问题,因为您实际上并没有任何错误检查。就像任何东西都可以返回一个 nullptr
  • 是的,因为那时文件已经加载了。您应该将东西包装在一个函数或其他东西中并多次调用它。重新初始化和关闭 python 解释器的成本很高。

标签: c++ python-3.x embedding


【解决方案1】:

docs

如果多次调用它们的初始化例程,某些扩展可能无法正常工作;如果应用程序多次调用 Py_Initialize() 和 Py_Finalize(),就会发生这种情况。

【讨论】:

  • 这对 TensorFlow 来说可能是正确的,尽管程序从未达到“完成”输出,这表明它甚至无法进行一次迭代。
  • 尝试将cout 更改为cerr
  • @Nejwiert 第一次迭代输出“Done”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-17
  • 2017-08-05
  • 2015-10-03
相关资源
最近更新 更多