在使用 Python C API 时,我发现 python 解释器在第二次初始化并在每次初始化后执行 import numpy
时崩溃。任何其他命令(例如导入时间
)都可以。
#include <Python.h>
int main(int argc, char ** argv)
{
while(1){
printf("Initializing python interpreter...\n");
Py_Initialize();
if(PyRun_SimpleString("import numpy")) {
exit(1);
}
printf("Finalizing python interpreter...\n");
Py_Finalize();
}
return 0;
}
上面的程序在我的两个测试系统(ubuntu 和 manjaro,无论我使用什么 python 版本)上崩溃,并在执行 import numpy
时出现段错误时间。
文档 ( https://docs.python.org/3/c-api/init.html?#c.Py_FinalizeEx ) 确实指出:如果多次调用某些扩展的初始化例程,则它们可能无法正常工作;如果应用程序多次调用 Py_Initialize() 和 Py_FinalizeEx() ,就会发生这种情况。
但是难道不应该有一种方法可以正确地清除解释器的内存,以便它可以多次初始化吗?例如,如果我有一个允许用户运行自定义 python 脚本的程序,那么应该可以多次运行相同的脚本,而无需重新启动程序。 有什么线索吗?
最佳答案
你不能只是声明所有内存都应该被清除/重置; Python 无法控制这一切。扩展模块是实际的共享对象/DLL 文件,它们实际上可以执行普通 C 程序可以执行的任何操作,并且不需要以核心 Python 解释器知道如何操作的方式注册所有操作。 em> 在完成时撤消它们。 Python 无法知道 SO/DLL 内存的这部分存储了必须清除的数据,而那部分是应该保留的静态数据。
完全有可能多次运行脚本,但您不需要通过最终确定和重新初始化来实现,您实际上只是在一次初始化中多次运行脚本(并希望它以幂等方式编写)。
作为替代方案,如果您使用的是类似 UNIX 的机器(即除 Windows 之外的任何机器),则可以通过不同的方式来完成“重置”,即通过 exec
执行您的程序来重新标记它与新的运行。这比 Python 本身的重置更彻底,但即便如此,它也不是万无一失的。例如如果文件描述符未在 O_CLOEXEC
模式下打开,它们将在新的 exec
进程中保持打开状态。
关于多次初始化时,Python C API 在 'import numpy' 处崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59314230/