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);