使用shelve反序列化时出现AttributeError:无法获取Employee属性的原因
问题原因与解决办法
核心原因
shelve模块底层依赖pickle实现对象的序列化与反序列化,而pickle保存对象时,并不会把类的完整代码存进文件,只记录类的名称和它所在的模块路径。
- 在定义
Employee和Manager的原模块中读取时,当前代码环境已经加载了这两个类的定义,pickle能直接找到对应类,所以读取正常。 - 在新文件中读取时,当前代码环境既没有这两个类的定义,也没正确导入,pickle找不到匹配的类,就会抛出
AttributeError: Can't get attribute Employee。
解决办法
1. 正确导入类(推荐)
在读取shelve文件的新文件中,从原模块导入对应的类。假设原模块名为employee_models.py,新文件代码示例:
import shelve # 从定义类的模块导入 from employee_models import Employee, Manager with shelve.open('emp_db') as db: emp = db['emp1'] print(emp.name) # 正常访问属性
注意:确保原模块在Python的搜索路径中(比如和新文件同目录,或者添加到sys.path)。
2. 复制类定义到新文件(不推荐)
把Employee和Manager的完整代码复制到新文件中,但这种方式存在隐患——如果原模块的类定义修改,新文件的类和序列化时的类不一致,会导致反序列化失败或数据异常。
3. 手动指定类查找路径(特殊场景用)
如果类所在的模块路径发生了变更(比如原模块被重命名),可以自定义pickle的类查找逻辑,示例:
import shelve import pickle # 假设原类现在在new_module里,原模块名是old_module class CustomUnpickler(pickle.Unpickler): def find_class(self, module, name): if module == 'old_module': module = 'new_module' return super().find_class(module, name) with open('emp_db.dat', 'rb') as f: unpickler = CustomUnpickler(f) emp = unpickler.load()
内容的提问来源于stack exchange,提问作者RezDom
相关产品推荐
相关产品推荐

