You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 17:35:22