NumPy 大数组做 |= 时段错误,留意旧 Python 3.14 构建
NumPy 临时数组的增强赋值触发段错误时,核对旧 Python 3.14 Linux 构建与栈展开路径,避免误判为文件损坏或内存不足。
读取 NetCDF 或处理 NumPy 数组时,Jupyter 内核直接退出,没有可捕获的 Python 异常;缩小数组后正常,把一行布尔表达式拆成两行也正常。如果本地崩溃栈经过 check_callers、try_binary_elide 和 backtrace,应检查解释器的构建来源,不要只围着文件损坏或 NumPy ABI 转。
这里针对的是 2026 年初部分 python-build-standalone Linux CPython 3.14 构建与栈展开的交互故障,其中明确出现过 Python 3.14.2、NumPy 2.4.2、Linux x86_64。它不是所有 Python 3.14、所有 Linux 或所有 WSL 环境都会发生的问题,也不是数组超过某个尺寸就必然内存不足。
表达式只是触发点
相关形状是一个普通布尔值与临时比较数组做增强赋值,例如 condition 初始为 False,随后执行 condition |= data == fill_value。在已确认环境中,512 × 512 的 float32 数组会触发崩溃,而略小的数组没有。这是该环境的触发边界,不是可以写进业务规则的安全尺寸。
NumPy 对部分临时数组有省略中间对象的优化。在有关实现中,它会检查 C 调用栈;崩溃可能出现在栈展开本身,甚至还没进入通常理解的“大数组运算”。因此,改小图片、给进程增加内存或修改 HDF5 引擎,都不能据此解释根因。
先保留原任务的故障栈和环境信息。下列命令只用于读取解释器与发行包信息,不需要重新执行会崩溃的数据处理:
python -c 'import sys; print(sys.version); print(sys.executable)'
python -m pip show numpy xarray
解释器路径若指向 uv 管理的 Python 安装,再核对该安装的构建日期和来源。仅有 Python 3.14.2 这个版本号,不能区分不同编译参数或发行批次。
可控代码先避开临时表达式路径
如果触发代码由自己维护,可以先把比较结果保存为有名字的数组,再合并条件:
comparison = data == fill_value
condition |= comparison
这保留逐元素比较与“或”的含义,避免让比较产生的临时对象立即进入同一个增强赋值表达式。应对照原数据检查掩码形状、类型和命中位置;这是一条局部绕过路径,不能当作解释器已修复的证明。
如果崩溃发生在 xarray 等依赖内部,不宜直接编辑 site-packages 中的一行后长期上线。依赖升级会覆盖手工修改,其他表达式也可能触发相同的栈展开问题。改为使用包含修复的解释器构建,通常比维护局部补丁更合适。
更换解释器时,核对构建而不只核对 uv 版本
该故障后来定位到 Python 构建中的 BOLT 优化与栈展开交互。构建侧调整过函数分割策略,随后带 frame pointer 的构建也已通过相关崩溃检查。2026 年 3 月的修复确认针对的是新构建,不能反推旧安装目录已经自动更新。
在单独环境中选择确认包含修复的 Python 发行构建,再按项目锁文件恢复依赖。保留解释器来源和构建信息,确保新环境没有继续指向原来的旧可执行文件。仅更新 uv 命令本身,或重复安装相同 NumPy wheel,都不足以证明解释器已被替换。
不要把最初关于引用计数、WSL 或 JIT 的猜测写成已经确认的原因,也不要为这个问题全局关闭安全检查或随机调整 BLAS 线程数。若新构建仍崩溃,先比较新的 C 栈;没有相同的 backtrace 路径,就需要按新证据排查。
验收应覆盖原先会崩溃的真实读取任务及其掩码结果,同时检查其他本地二进制依赖能否正常导入。若只在纯 NumPy 小样本里不再退出,仍不能代替原来的 NetCDF 解码或整批数据处理完成。


