pickle序列化自定义Title类报PicklingError属性查找失败怎么办
问题说明
使用Python的pickle模块执行自定义类实例的序列化写入操作时抛出异常,错误提示__main__模块下Title类的属性查找失败。
复现代码
import pickle class Title: def __init__(self, title, platform, size, price): self.title = title self.platform = platform self.size = size self.price = price def display(self): print("Printing the title details", '\n') print('TITLE:{} , PLATFORM:{}, SIZE:{} , PRICE:{}' .format(self.title, self.platform, self.size, self.price)) g = Title("Battlefield V", "Steam", "65GB", "1200") """ Serialisation to be done of the instance g using pickle module""" with open('game.csv', 'wb') as f: pickle.dump(g, f) print('serialization is complete - file object created') with open('game.ser', 'rb') as f: game_obj = pickle.load(f) print('Deserialization is complete - python obj created') game_obj.display()
报错信息
pickle.PicklingError: Can't pickle <class '__main__.Title'>: attribute lookup Title on __main__ failed
错误原因
- 代码存在基础逻辑错误:序列化写入的文件名为
game.csv,反序列化时却尝试读取game.ser,两个路径不一致,即使序列化成功也会触发文件不存在的错误。 - 触发属性查找失败的PicklingError核心原因是:pickle序列化自定义类时,要求被序列化的类必须定义在模块顶层作用域,执行序列化/反序列化操作时,Python解释器可以直接在当前模块的全局命名空间中定位到该类。该错误通常由以下不规范写法导致:
- 将
Title类定义写在函数、条件判断、循环等嵌套代码块内部,而非文件顶格的顶层位置 - 在交互式运行环境(Python自带Shell、IPython、Jupyter Notebook)中逐行/逐块运行类定义和序列化代码,类未被正确注册到
__main__模块的全局属性表 - 保存代码的文件名和Python标准库重名(比如将脚本命名为
pickle.py),导致import pickle时导入逻辑混乱
- 将
修复步骤
- 检查
Title类的定义位置,确保其在py文件中顶格编写,不嵌套在任何函数、分支、循环代码块内 - 统一序列化、反序列化操作使用的文件路径,建议使用
.pkl作为pickle序列化文件的专属后缀,避免和csv等其他格式文件混淆 - 检查脚本文件名,不要命名为
pickle.py,防止和标准库模块重名引发冲突 - 不要在交互式环境中逐段运行这段涉及自定义类序列化的代码,将完整代码保存为独立py文件后执行
修复后可运行代码
import pickle # 自定义类必须放在模块顶层作用域 class Title: def __init__(self, title, platform, size, price): self.title = title self.platform = platform self.size = size self.price = price def display(self): print("Printing the title details\n") print('TITLE:{} , PLATFORM:{}, SIZE:{} , PRICE:{}' .format(self.title, self.platform, self.size, self.price)) if __name__ == '__main__': g = Title("Battlefield V", "Steam", "65GB", "1200") # 统一序列化和反序列化使用的文件路径 save_path = 'game.pkl' # 序列化写入 with open(save_path, 'wb') as f: pickle.dump(g, f) print('serialization is complete - file object created') # 反序列化读取同一路径 with open(save_path, 'rb') as f: game_obj = pickle.load(f) print('Deserialization is complete - python obj created') game_obj.display()
正常运行输出
serialization is complete - file object created Deserialization is complete - python obj created Printing the title details TITLE:Battlefield V , PLATFORM:Steam, SIZE:65GB , PRICE:1200
内容的提问来源于stack exchange,提问作者Mandar Gite
相关产品推荐
相关产品推荐

