该错误源于numpy 1.16.0起为修复cve-2019-6446漏洞,默认禁用pickle反序列化,当加载含python对象(如list、str)的.npy文件时触发;纯数值数组不受影响,强行设allow_pickle=true可绕过但存在远程代码执行风险。

为什么 numpy.load() 会报 ValueError: Cannot load file containing pickled data when allow_pickle=False?
这不是文件损坏,而是 NumPy 从 1.16.0 版本起默认禁用了 pickle 反序列化——所有用旧版本(尤其是含自定义对象、列表、字符串数组)保存的 .npy 文件,加载时都会触发这个错误。核心矛盾是安全策略升级,不是数据丢失。
- 该错误只在含 Python 对象(如
list、str、自定义类实例)的.npy中出现,纯数值数组通常不受影响 - 强行设
allow_pickle=True能绕过,但必须确认来源可信,否则存在远程代码执行风险 - 如果文件真损坏(比如截断、写入中断),错误会是
OSError: Failed to read from file或ValueError: invalid shape in fixed-type descriptor,和 pickle 错误无关
如何安全地加载含 pickle 数据的 .npy 文件?
先验证文件是否可读、是否真含 pickle 内容,再决定是否启用 allow_pickle:
- 用
file命令或head -c 20 filename.npy查看前几十字节:若含NUMPY\x01\x00后紧跟0x80(即 pickle 协议标识),说明用了 pickle 序列化 - 尝试最小化加载:
np.load("broken.npy", mmap_mode="r")—— 若能 mmap 成功,说明文件结构完整,只是反序列化被拦住 - 确认可信后,显式传参:
np.load("broken.npy", allow_pickle=True);不要全局修改np.set_printoptions或环境变量
如果文件真的损坏(非 pickle 问题),怎么抢救?
损坏通常表现为读取时崩溃、shape 异常或 dtype 错乱。没有通用修复工具,但可分步试探:
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
- 用
xxd -l 100 filename.npy检查 magic number 是否为93 4e 55 4d 50 59(即\x93NUMPY),不是则文件头已毁,基本不可恢复 - 对比正常
.npy文件头长度(通常 20+ 字节),若当前文件小于该值,说明 header 截断,无法解析 - 若 header 完整但数据区损坏,可用
np.memmap手动跳过坏块:arr = np.memmap("broken.npy", dtype="float32", mode="r", offset=HEADER_SIZE),再用arr[:valid_length]截取有效部分
如何避免下次再遇到这类问题?
根本解法是统一保存策略,不依赖 pickle:
- 保存纯数值数组时,始终用
np.save(..., allow_pickle=False)(NumPy ≥1.16 默认行为) - 需要存 list/str 等混合类型,改用
np.savez或np.savez_compressed,它们将每个数组单独序列化,不触发全局 pickle 开关 - 长期归档场景,优先选 HDF5(
h5py)或 Apache Parquet(pyarrow),二者对类型和损坏更鲁棒
真正麻烦的不是报错本身,而是有人把 allow_pickle=True 当成万能开关加进生产脚本里——一旦文件来源不可控,等于主动打开沙箱逃逸入口。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










