Python C API - 重新加载模块
Posted
技术标签:
【中文标题】Python C API - 重新加载模块【英文标题】:Python C API - Reload a module 【发布时间】:2015-02-13 12:12:30 【问题描述】:我使用 Python 3.4 和 Visual 2010。 我正在使用 C API 嵌入 Python,以便为用户提供一些脚本功能来处理他的数据。我从我的 C++ 代码中调用用户定义的 python 函数。例如,我调用用户必须在 Python 文件中定义的特定函数,例如 Apply()。 假设用户有一个文件 test.py,他在其中定义了一个处理一些数据的函数 Apply()。 我所要做的就是导入他的模块并从 C++ 中获取指向他的 python 函数的“指针”。
PySys_SetPath(file_info.absolutePath().toUtf8().data()));
m_module = PyImport_ImportModule(module_name.toUtf8().data());
if (m_module)
m_apply_function = PyObject_GetAttrString(m_module, "Apply");
m_main_dict = PyModule_GetDict(m_module);
到目前为止,一切都很好。但是如果用户修改了他的脚本,他的函数的新版本就从不考虑在内。我必须重新启动我的程序才能使其工作......我在某处读到我需要重新加载模块并获取函数的新指针,但 PyImport_ReloadModule 返回 NULL 并显示“导入错误”。
// .... code ....
// Reload the module
m_module = PyImport_ReloadModule(m_module);
有什么想法吗? 最好的祝福, 普吉尔
【问题讨论】:
模块很可能没有加载。能不能加个 PyErr_Print 看看有没有异常,是哪个异常? 我无法使用 PyErrorPrint,因为我使用的是 Python C API。但是经过一些检查,我有一个“导入找不到模块,或者在模块中找不到名称”。这很奇怪,因为我刚刚在同一个地方加载了模块(PySys_SetPath 已用于此)。如果我改用 PyImport_ImportModule,它可以工作,我得到一个有效的指针,但没有更新。 PyErr_Print 是一个 c api 函数,是 PyErr_PrintEx 的别名。关于重新加载和名称解析有一些注意事项。是否有可能只重新启动解释器? 你试过importlib.reload(module)
吗?第二次拨打PyImport_ImportModule
毫无意义;它可能只是从sys.modules
返回缓存值。确保PySys_SetPath
参数包含所有 必要的路径(包括用户脚本所需的pythonpath)。
@TasosVogiatzoglou :我知道 PyErr_Print 是一个 C 函数,但它直接打印到我看不到的 python 解释器(sys.stderr)中。就像我说的,我嵌入了 Python,所以我现在看不到解释器的输出,我必须使用 PyErr_Fetch(&ptype, &pvalue, &ptraceback)
捕获异常和堆栈跟踪,但这并不容易。重新启动解释器可能是一种选择,但显然不是最好的,因为我必须停止任何正在运行的会话。
【参考方案1】:
在我的第一篇文章的 cmets 中找到了答案(谢谢 J.F Sebastian),PySys_SetPath
还必须包含 PYTHONPATH。就我而言,这就是 PyImport_ReloadModule
失败的原因。
QString sys_path = file_info.absolutePath() + ";" + "C:\\Python34\\Lib";
PySys_SetPath(UTF8ToWide(sys_path.toUtf8().data()));
m_module = PyImport_ReloadModule(m_module); // Ok !
【讨论】:
以上是关于Python C API - 重新加载模块的主要内容,如果未能解决你的问题,请参考以下文章