停止嵌入python
Stop embedded python
我在c++插件中嵌入python。该插件在每次会话期间调用python算法数十次,每次向算法发送不同的数据。一切顺利
但是现在我有一个问题:算法有时需要几分钟来求解并返回一个解,而在这段时间内,条件的变化往往会使解变得无关紧要。因此,我想要的是在任何时刻停止算法的运行,并在其他数据集之后立即运行它。
这是我目前为止嵌入python的c++代码:
void py_embed (void*data){
counter_thread=false;
PyObject *pName, *pModule, *pDict, *pFunc;
//To inform the interpreter about paths to Python run-time libraries
Py_SetProgramName(arg->argv[0]);
if(!gil_init){
gil_init=1;
PyEval_InitThreads();
PyEval_SaveThread();
}
PyGILState_STATE gstate = PyGILState_Ensure();
// Build the name object
pName = PyString_FromString(arg->argv[1]);
if( !pName ){
textfile3<<"Can't build the object "<<endl;
}
// Load the module object
pModule = PyImport_Import(pName);
if( !pModule ){
textfile3<<"Can't import the module "<<endl;
}
// pDict is a borrowed reference
pDict = PyModule_GetDict(pModule);
if( !pDict ){
textfile3<<"Can't get the dict"<<endl;
}
// pFunc is also a borrowed reference
pFunc = PyDict_GetItemString(pDict, arg->argv[2]);
if( !pFunc || !PyCallable_Check(pFunc) ){
textfile3<<"Can't get the function"<<endl;
}
/*Call the algorithm and treat the data that is returned from it
...
...
*/
// Clean up
Py_XDECREF(pArgs2);
Py_XDECREF(pValue2);
Py_DECREF(pModule);
Py_DECREF(pName);
PyGILState_Release(gstate);
counter_thread=true;
_endthread();
};
编辑:python的算法不是我的工作,我不应该改变它
这是基于对python的粗略了解,以及快速阅读python文档。
PyThreadState_SetAsyncExc
允许你在运行的python线程中注入异常。
在某个线程中运行python解释器。在另一个线程中,PyGILState_STATE
然后PyThreadState_SetAsyncExc
进入主线程。(这可能需要一些前期工作来教python解释器关于第二个线程的内容)。
除非你正在运行的python代码充满了"catch all ",否则这会导致它终止执行。
您还可以查看代码以创建python子解释器,这将允许您在旧脚本关闭时启动新脚本。
Py_AddPendingCall
也是诱人的使用,但周围有足够的警告,也许不是。
对不起,你的选择很短。您可以更改python代码(好吧,插件-不是一个选项)或在另一个PROCESS上运行它(中间有一些不错的ipc)。然后你可以使用系统api来清除它
所以,我终于想到了一个解决方案(更像是一个变通的方法)。
我没有终止正在运行算法的线程(我们称它为T1),而是创建了另一个线程(t2),其中包含当时相关的数据集。
在每个线程中我都这样做:
thread_counter+=1; //global variable
int thisthread=thread_counter;
,在python给出解决方案后,我只需验证哪个是最新的,来自T1还是来自T2:
if(thisthread==thread_counter){
/*save the solution and treat it */
}
就计算机的工作量而言,这显然不是最好的解决方案,但它满足了我的目的。
谢谢大家的帮助
我一直在思考这个问题,我同意子解释器可能为您提供一个可能的解决方案https://docs.python.org/2/c-api/init.html#sub-interpreter-support。它支持创建新的解释器和结束现有解释器的呼吁。虫子&注意事项部分描述了一些问题,这些问题取决于您的体系结构,可能会出现问题,也可能不会出现问题。
另一个可能的解决方案是使用python多处理模块,并在工作线程中测试一个全局变量(类似于time_to_die)。然后从父进程中获取GIL,设置变量,释放GIL并等待子进程完成。但是我想到了另一个主意。为什么不直接使用fork(),在子线程中初始化你的python解释器,当父线程决定该结束python线程时,就杀死它。像这样:
void process() {
int pid = fork();
if (pid) {
// in parent
sleep(60);
kill(pid, 9);
}
else{
// in child
Py_Initialize();
PyRun_SimpleString("# insert long running python calculation");
}
}
- 如何运行位于boost/libs/python/example/tutorial目录中的hello.cpp和Jamfil
- Pybind11:将元组列表从Python传递到C++
- 如何在c++中使用引用实现类似python的行为
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 递归列出所有目录中的C++与Python与Ruby的性能
- IPC使用多个管道和分支进程来运行Python程序
- 从python中调用C++函数并获取返回值
- Python 3.7 和 excess_args 的 SWIG 问题
- Python中的for循环与C++有何不同
- 使用Pybind11向Python公开Eigen::张量
- Python str to C++ to Python str
- 如何使用Python从C++中读取谷物序列化数据
- 如何在C++中使用pybind11加载一个pickle python列表
- 如何在c++中使用system()来运行包含空格的python脚本
- python集合的C++等价物是什么.计数器
- 如果C++对象的类在另一个boost模块中声明,如何使用boost将指向该对象的指针返回到python
- 从python调用openMP共享库时,未定义opnMP函数
- 使用JsonCpp将数据返回到带有pybind11的python会在python调用中产生Symbol not foun
- 如何将真正的字符串从python c-api转换为python脚本
- Python ctype 'c_char_p' Memory Leak