我使用boost.python来调用脚本。每个python脚本都有3个函数:
这个课程不需要解释:
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引发的异常是无法捕获的。为什么?以及如何预防?
答案 0 :(得分:1)
使用Py_Finalize()
可能是问题所在。根据Boost 1.55文档,您shouldn't use Py_Finalize()
with Boost.Python。看起来您的程序确实不需要最终确定,因此您可以尝试从~PyInit()
删除该来电。
如果由于某种原因确实需要最终确定,可以查看Py_NewInterpreter()
。
对于您的“无法捕获的异常”问题,这通常会导致同时出现两个活动异常。当发生这种情况时,C ++将简单地中止。这可能(或可能不是)代码中发生的事情。