PyEval_CallObject环路偶尔失败
-
19-09-2019 - |
题
我奋力有点使用Python C API。我打电话蟒蛇方法做一些游戏AI在大约60赫兹。它的工作原理的时间,但在一个NULL返回值每秒左右调用PyEval_CallObject结果的最的。如果我正确地检测该错误并继续循环,都是很好的下一个第二左右,于是再次发生错误。
我怀疑我做错了什么与裁判计数,但我无法弄清楚它是什么:
int script_do_ai(struct game_data_t* gd)
{
PyObject *pAiModule, *pResult;
float result=0.0;
pResult = NULL;
pAiModule = PyImport_Import(PyString_FromString("ai_script"));
是的,我导入模块每次迭代。有必要吗?如果我存储pAiModule作为一个全球性的,我得到一个硬性事故约一秒钟后。
pResult = PyEval_CallObject(PyObject_GetAttrString(pAiModule, "do_ai"),
Py_BuildValue("f", gd->important_float))
if (pResult != NULL)
{
PyArg_Parse(pResult, "f", &result);
Py_DECREF(pResult);
ConquerEnemies(result); //you get the idea
}
else //this happens every 75 or so iterations thru the loop
{
if (PyErr_ExceptionMatches(PyExc_SomeException)) //? not sure what to do here
{
我一直无法找出如何提取例外的是,无论是...没有测试的每一个的异常
}
}
我是甚至接近这样做对吗?就像我说的,它主要是工作,但我真的很想知道为什么我收到一个错误。
感谢您事先的任何帮助。
解决方案
您可以随时为你喜欢叫PyImport_Import()
,但是你会不断得到相同的模块对象返回。 Python的缓存进口。另外,代替创建新Python字符串和泄漏参考(以及因此的对象),则应该只使用PyImport_ImportModule()
,这需要一个const char *
。
PyImport_Import*()
返回一个新的参考,但是,你应该调用它的Py_DECREF()
时,即可大功告成。存储在全球模块不应该是一个问题,只要你拥有它的一个引用(你做什么,在这里。)
在您的来电PyEval_CallObject()
你不检查Py_BuildValue()
错误的结果,而你也没有打电话Py_DECREF()
当你用它做,所以你泄露该对象也是如此。
为了给一个Python浮点转换为C双键的,你应该只调用PyFloat_AsDouble()
,而不是摆弄PyArg_Parse()
(并牢记测试例外)
下到实际的错误处理:当你真正想要测试是否异常匹配的东西PyErr_ExceptionMatches()
才有用。如果你想知道,如果发生异常,或者获得实际的异常对象,PyErr_Occurred()
是你应该叫什么。它返回当前异常型(不是实际的异常对象),为借用参考,或NULL,如果没有设置。如果你只想打印一个回溯到stderr,PyErr_Print()
和PyErr_Clear()
是要使用什么。对于你的代码中的实际错误的更细粒度的检查,PyErr_Fetch()
让你与它(它可以让你在相同的信息Python代码sys.exc_info()
)。所有的事情考虑,你很少想获取有关当前异常对象和追踪深地进入异常在C代码处理。