C++循环调用Python导入Numpy触发访问违例异常的求助
问题:嵌入Python的C++程序循环导入numpy时第二轮崩溃
在Windows 10的Visual Studio 2022中运行嵌入Python模块的C++程序,循环内执行numpy导入操作时,第一轮正常,第二轮导入时直接抛出异常。
最小复现代码:
#include <C:\Program Files\Python39\include\Python.h> #include <iostream> using namespace std; int main() { for (int i = 0; i < 5; i++) { cout << i << endl; Py_Initialize(); PyRun_SimpleString("import numpy as np"); PyRun_SimpleString("arr = np.array([1,2,3])"); PyRun_SimpleString("print(arr)"); Py_Finalize(); } }
控制台输出:
0 [1 2 3] 1 Traceback (most recent call last): File "<string>", line 1, in <module>
Visual Studio错误信息:
Exception thrown at 0x00007FFCB9461319 (_multiarray_umath.cp39-win_amd64.pyd) in App4.exe: 0xC0000005: Access violation writing location 0x0000000000000008.
原因分析
numpy这类基于C实现的扩展模块,在调用Py_Finalize()后无法完全清理自身的全局状态和内存资源。当再次调用Py_Initialize()重新初始化Python解释器时,残留的旧状态会与新解释器实例发生冲突,触发内存访问违规。Python官方文档明确说明,多次调用Py_Initialize()和Py_Finalize()并不被所有扩展模块支持,尤其是包含底层C逻辑的模块。
解决方法
方法1:将初始化和清理移到循环外
只初始化一次Python解释器,循环内仅执行业务逻辑,最后统一清理:
#include <C:\Program Files\Python39\include\Python.h> #include <iostream> using namespace std; int main() { // 仅初始化一次 Py_Initialize(); for (int i = 0; i < 5; i++) { cout << i << endl; PyRun_SimpleString("import numpy as np"); PyRun_SimpleString("arr = np.array([1,2,3])"); PyRun_SimpleString("print(arr)"); } // 仅清理一次 Py_Finalize(); return 0; }
方法2:避免重复导入模块
将numpy导入语句移到循环外,减少重复操作的同时彻底规避状态冲突:
#include <C:\Program Files\Python39\include\Python.h> #include <iostream> using namespace std; int main() { Py_Initialize(); // 提前导入numpy,循环内直接使用 PyRun_SimpleString("import numpy as np"); for (int i = 0; i < 5; i++) { cout << i << endl; PyRun_SimpleString("arr = np.array([1,2,3])"); PyRun_SimpleString("print(arr)"); } Py_Finalize(); return 0; }
方法3:使用子进程执行循环逻辑(备选)
如果业务必须在每次循环中重新初始化解释器,可以为每次循环启动独立子进程,隔离进程内的状态冲突。但这种方式会带来额外性能开销,仅适用于特殊场景。
内容的提问来源于stack exchange,提问作者Johan hvn
相关产品推荐
相关产品推荐

