如何加载Jupyter Notebook中用自定义类保存的joblib文件
报错原因
joblib 底层依赖 pickle 实现序列化,序列化自定义类实例时不会存储类的完整实现代码,仅会记录类所属的模块名、类名两个核心信息。反序列化时会自动到对应模块中检索匹配的类定义:
- 你在原 Jupyter Notebook 中定义
Duck类时,该类默认归属于__main__模块,当前 Notebook 运行时__main__模块存在Duck定义,因此可以正常加载 - 切换到新的 Notebook 或
.py脚本后,新的运行环境中__main__模块没有预先定义Duck类,因此会抛出属性找不到的错误
解决方法
方法1:预定义同版本类(临时适配)
反序列化操作执行前,先在当前运行环境中定义和序列化时完全一致的 Duck 类,类的属性、方法、继承关系都不能有差异,示例代码如下:
# 先完整定义和序列化时一模一样的Duck类 class Duck: def quack(self): print("Quack!") # 再执行加载逻辑 import joblib my_duck = joblib.load("my_duck.joblib")
方法2:公共模块托管类(推荐方案)
把自定义类的实现写到单独的公共 .py 文件中,序列化、反序列化场景都从该公共模块导入类使用,彻底避免跨环境找不到类的问题:
- 新建
duck_utils.py文件,写入Duck类的完整实现 - 序列化时的代码:
from duck_utils import Duck import joblib duck = Duck() joblib.dump(duck, "my_duck.joblib")
- 任意新环境反序列化时的代码:
from duck_utils import Duck import joblib my_duck = joblib.load("my_duck.joblib")
方法3:手动注册类到__main__模块
如果不想修改类的引入方式,可以手动把类注册到运行环境的 __main__ 模块中,示例代码如下:
import __main__ import joblib # 定义Duck类 class Duck: def quack(self): print("Quack!") # 手动注册到__main__模块 __main__.Duck = Duck # 加载序列化文件 my_duck = joblib.load("my_duck.joblib")
注意事项
- 类定义必须和序列化时完全一致,如果类的方法、属性结构发生了变更,加载后的实例调用时可能会出现不可预期的异常
- 不要加载来源不明的 joblib/pickle 序列化文件,这类文件可能包含恶意执行代码,存在安全风险
内容的提问来源于stack exchange,提问作者J. Doe
相关产品推荐
相关产品推荐

