PyRun_File在Python C-API中使用递归函数

时间:2018-03-11 15:02:41

标签: python 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

关于如何进行的任何想法?

编辑:

平台:Windows 10 x64 Python:2.7.14

1 个答案:

答案 0 :(得分:0)

说明:

在以下行中,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);