使用boost.python,奇怪的进程失败了

时间:2014-05-27 12:37:49

标签: python c++ exception boost

我使用boost.python来调用脚本。每个python脚本都有3个函数:

  • 初始化 - 必须在开始时调用
  • 取消初始化 - 必须在结束时调用以关闭每个对象。
  • 进程 - 必须在Initialize和Uninitialize之间多次调用。

这个课程不需要解释:

class PyInit
{
public:
    PyInit() { Py_Initialize(); }
    ~PyInit() {  Py_Finalize();  }
};

该类创建PyInit对象实例,然后初始化所有Python对象并调用" Initialize()"构造函数中的python函数。 并且呼叫" Uninitialize()"在析构函数。

这个课程有功能"过程"多次在课外调用它。

class PyGuard
{
public:
    explicit PyGuard(const char* pypath)
    {
      try
      {
        _main_module = boost::python::import("__main__");
        _main_namespace = _main_module.attr("__dict__");
        boost::python::object ignored = exec_file(pypath, _main_namespace);
        _Initialize = _main_namespace["Initialize"];
        _Process = _main_namespace["Process"];
        _Uninitialize = _main_namespace["Uninitialize"];

        _InitRes = _Initialize();
        _ProcRes = boost::python::object();
      }
      catch(boost::python::error_already_set&)
      {
        string res;
        py_utils::err_parse(res);
        throw string("Python exception: " + res);
      }
      catch(std::exception& e)
      {
          throw string("C++ exception: " + string(e.what()));
      }
      catch(...)
      {
          throw string("Unhandled exception!");
      }
    }
    virtual ~PyGuard()
    {
        _Uninitialize(_InitRes, _ProcRes);
    }
    void Process()
    {
        _ProcRes = _Process(_InitRes, _ProcRes);
    }


private:
    py_utils::PyInit _initPython;

    boost::python::object _InitRes;
    boost::python::object _ProcRes; 

    boost::python::object _Process;
    boost::python::object _Initialize;
    boost::python::object _Uninitialize;

    boost::python::object _main_module;
    boost::python::object _main_namespace;
};

仅作为"过程"失败了" boost :: python :: error_already_set"例外,PyGuard的当前实例被删除,然后创建新的实例。避免可能作为隐藏异常结果的隐藏依赖项。

因此,在异常之后,所有python东西都被删除(甚至调用Py_Finalize()),然后再次创建。

然而,在4-10个这样的例外之后,整个c ++过程都会失败。

跌倒,甚至避开捕手:

  try
  {
      _PyGuard = make_shared<PyGuard>("my script");
      while(true)
      {
        try {
          _PyGuard->Process();
        }
        catch()
        {
              bool inited = false;
              while(!inited)
              {
                try
                {
                _pyGuard = nullptr;
                _pyGuard = make_shared<PyGuard>("script path.txt");
                inited = true;
                }
                catch(string& e)
                {
                }
              }
        }
      } 
      _PyGuard = nullptr;
  } 
  catch(...)
  {
      //falling, it never being catched here.
  }

所以,我的问题是,为什么它会崩溃并且无法捕捉?

我刚刚发现它符合要求:

_pyGuard = make_shared<PyGuard>("script path.txt"); 

调用,所以我觉得Python引发的异常是无法捕获的。为什么?以及如何预防?

1 个答案:

答案 0 :(得分:1)

使用Py_Finalize()可能是问题所在。根据Boost 1.55文档,您shouldn't use Py_Finalize() with Boost.Python。看起来您的程序确实不需要最终确定,因此您可以尝试从~PyInit()删除该来电。

如果由于某种原因确实需要最终确定,可以查看Py_NewInterpreter()

对于您的“无法捕获的异常”问题,这通常会导致同时出现两个活动异常。当发生这种情况时,C ++将简单地中止。这可能(或可能不是)代码中发生的事情。