Python3使用copy模块序列化_thread.RLock触发TypeError问题咨询
问题根因
- Python2.7中
threading.RLock为纯Python实现,默认支持pickle序列化,且copy.copy处理该类型时会兼容返回原引用或合法拷贝对象,不会触发报错。 - Python3.x中RLock改为C语言实现的
_thread.RLock类型,本身不支持pickle序列化,而标准库copy.copy处理无自定义__copy__方法的C扩展对象时,会默认调用pickle协议尝试重建对象,因此直接抛出不可序列化的错误。 - 你之前直接跳过锁属性的赋值,导致新实例缺失同步锁,多线程状态更新时的通知逻辑失效,才会需要手动刷新UI才能看到最新状态。
可行解决方案
不要直接跳过锁属性的处理,根据你的业务场景选择以下任意一种方案即可:
方案1:在自定义copy方法中新增RLock类型判断
修改你的自定义copy方法,遇到RLock类型时单独处理,不要调用默认的copy.copy:
from copy import copy import threading def copy(self, cls=None): # 类方法 if cls is None: cls = self.__class__ new_self = cls() for key, value in self.__dict__.items(): if self.should_copy_attribute(key, value): # 递归引用处理,指向新实例本身避免死循环 if value is self: value = new_self # 新增RLock类型处理逻辑 elif isinstance(value, threading.RLock): # 场景A:新实例需要独立的同步锁,和原实例互不影响 value = threading.RLock() # 场景B:新实例需要和原实例共享状态、共用同一把锁,直接复用原对象即可 # value = value else: value = copy(value) new_self.__dict__[key] = value return new_self
方案2:针对固定锁属性名单独处理
如果锁的属性名固定为你注释中的multithread_lock,可以直接针对该key单独赋值,比通用类型判断性能更好、更精准:
def copy(self, cls=None): # 类方法 if cls is None: cls = self.__class__ new_self = cls() for key, value in self.__dict__.items(): if self.should_copy_attribute(key, value): if value is self: value = new_self elif key == "multithread_lock": # 按需选择新建锁或者复用原锁 value = threading.RLock() else: value = copy(value) new_self.__dict__[key] = value return new_self
方案3:给包含RLock的类自定义__copy__方法
在你定义了RLock属性的类中新增__copy__方法,告诉标准库copy模块该类的拷贝规则,不需要走默认的pickle逻辑,适配性更强。
内容的提问来源于stack exchange,提问作者Immortal
相关产品推荐
相关产品推荐

