PyRun_File 在 Python C-API 中具有递归函数
PyRun_File with recursive functions in Python C-API
我正在努力将 python 解释器嵌入到一个更大的系统中,其中一个功能是 运行 一个 python 脚本。
使用以下代码片段进行测试效果很好,但使用递归函数时只会执行第一次调用然后崩溃
//C++ code
int main()
{
Py_Initialize();
PyObject* m_pMainModule = PyImport_AddModule("__main__");
PyObject* m_pGlobalDict = PyModule_GetDict(m_pMainModule);
PyObject* m_pLocalDict = PyDict_New();
PyObject* fd = PyFile_FromString("script.py", "r");
if (fd == NULL)
{
PyErr_SetString(PyExc_IOError, "File not found");
}
PyObject * s = PyRun_File(PyFile_AsFile(fd), "script.py", Py_file_input, m_pGlobalDict, m_pLocalDict);
Py_XDECREF(fd);
Py_XDECREF(s);
if (PyErr_Occurred())
{
std::string result;
PyObject* ptype;
PyObject* pvalue;
PyObject* ptraceback;
PyErr_Fetch(&ptype, &pvalue, &ptraceback);
PyErr_NormalizeException(&ptype, &pvalue, &ptraceback); // in order to convert pvalue from tuples to real objects
//Attach exception name first
PyObject* objectStr = PyObject_GetAttrString(ptype, "__name__");
result = PyString_AS_STRING(objectStr);
result = "Exception: " + result;;
Py_XDECREF(objectStr);
objectStr = PyObject_Str(pvalue);
if (objectStr != NULL) {
result = result + " was raised with error message : " + PyString_AS_STRING(objectStr);
Py_XDECREF(objectStr);
}
std::cout << result;
}
return 0;
}
这是我使用的python脚本
def fac(i):
print "Call to FAC(",i,") !"
if i <= 1:
return 1
else:
return i*fac(i-1)
print "Hello world"
print fac(4)
这是输出
Hello world
Call to FAC( 4 ) !
Exception: NameError was raised with error message : global name 'fac' is not defined
而预期的输出(当运行直接通过调用脚本时)
Hello world
Call to FAC( 4 ) !
Call to FAC( 3 ) !
Call to FAC( 2 ) !
Call to FAC( 1 ) !
24
关于如何进行的任何想法?
编辑:
平台:Windows10 x64
Python: 2.7.14
解释:
在下一行中,PyRun_File
使用了两个不同的词典;一种用于全局,一种用于本地。
PyObject * s = PyRun_File(PyFile_AsFile(fd), "script.py", Py_file_input, m_pGlobalDict, m_pLocalDict);
fac
函数名添加到文件本地的奇怪部分。
我不知道为什么,但我真的很想知道。
因此递归调用失败,因为函数或全局的局部变量中没有fac
。
解决方案:
为本地和全局传递相同的字典
PyObject * s = PyRun_File(PyFile_AsFile(fd), "script.py", Py_file_input, m_pGlobalDict, m_pGlobalDict);
我正在努力将 python 解释器嵌入到一个更大的系统中,其中一个功能是 运行 一个 python 脚本。
使用以下代码片段进行测试效果很好,但使用递归函数时只会执行第一次调用然后崩溃
//C++ code
int main()
{
Py_Initialize();
PyObject* m_pMainModule = PyImport_AddModule("__main__");
PyObject* m_pGlobalDict = PyModule_GetDict(m_pMainModule);
PyObject* m_pLocalDict = PyDict_New();
PyObject* fd = PyFile_FromString("script.py", "r");
if (fd == NULL)
{
PyErr_SetString(PyExc_IOError, "File not found");
}
PyObject * s = PyRun_File(PyFile_AsFile(fd), "script.py", Py_file_input, m_pGlobalDict, m_pLocalDict);
Py_XDECREF(fd);
Py_XDECREF(s);
if (PyErr_Occurred())
{
std::string result;
PyObject* ptype;
PyObject* pvalue;
PyObject* ptraceback;
PyErr_Fetch(&ptype, &pvalue, &ptraceback);
PyErr_NormalizeException(&ptype, &pvalue, &ptraceback); // in order to convert pvalue from tuples to real objects
//Attach exception name first
PyObject* objectStr = PyObject_GetAttrString(ptype, "__name__");
result = PyString_AS_STRING(objectStr);
result = "Exception: " + result;;
Py_XDECREF(objectStr);
objectStr = PyObject_Str(pvalue);
if (objectStr != NULL) {
result = result + " was raised with error message : " + PyString_AS_STRING(objectStr);
Py_XDECREF(objectStr);
}
std::cout << result;
}
return 0;
}
这是我使用的python脚本
def fac(i):
print "Call to FAC(",i,") !"
if i <= 1:
return 1
else:
return i*fac(i-1)
print "Hello world"
print fac(4)
这是输出
Hello world
Call to FAC( 4 ) !
Exception: NameError was raised with error message : global name 'fac' is not defined
而预期的输出(当运行直接通过调用脚本时)
Hello world
Call to FAC( 4 ) !
Call to FAC( 3 ) !
Call to FAC( 2 ) !
Call to FAC( 1 ) !
24
关于如何进行的任何想法?
编辑:
平台:Windows10 x64 Python: 2.7.14
解释:
在下一行中,PyRun_File
使用了两个不同的词典;一种用于全局,一种用于本地。
PyObject * s = PyRun_File(PyFile_AsFile(fd), "script.py", Py_file_input, m_pGlobalDict, m_pLocalDict);
fac
函数名添加到文件本地的奇怪部分。
我不知道为什么,但我真的很想知道。
因此递归调用失败,因为函数或全局的局部变量中没有fac
。
解决方案:
为本地和全局传递相同的字典
PyObject * s = PyRun_File(PyFile_AsFile(fd), "script.py", Py_file_input, m_pGlobalDict, m_pGlobalDict);