You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python序列化含ruamel.yaml实例的对象时pickle报错的解决咨询

解决pickle序列化含ruamel.yaml.YAML实例对象时报错的问题

问题原因

ruamel.yaml的YAML实例内部会保留无法被pickle序列化的IO相关状态(比如你推测的文件流引用),直接序列化包含该实例的对象时,就会触发TypeError: cannot pickle '_io.TextIOWrapper' object错误。

解决方案

方案一:自定义序列化/反序列化逻辑(适用于实例间YAML配置不同的场景)

通过实现类的__getstate__和__setstate__方法,控制序列化时只保留必要数据,反序列化时重建带自定义配置的YAML实例:

import pickle
from ruamel.yaml import YAML

class C:
    def __init__(self):
        self.yaml = YAML()
        # 模拟添加自定义representer
        self.yaml.representer.add_representer(str, self.custom_str_representer)
        with open("test.yaml", 'r') as yamlFile:
            self.my_yaml = self.yaml.load(yamlFile)
    
    def custom_str_representer(self, dumper, data):
        # 自定义representer逻辑示例
        return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='"')
    
    def __getstate__(self):
        # 序列化时剔除无法pickle的yaml实例
        state = self.__dict__.copy()
        del state['yaml']
        return state
    
    def __setstate__(self, state):
        # 反序列化时恢复属性并重建带自定义配置的yaml实例
        self.__dict__.update(state)
        self.yaml = YAML()
        self.yaml.representer.add_representer(str, self.custom_str_representer)

# 测试序列化与反序列化
c = C()
with open("test.pkl", 'wb') as output:
    pickle.dump(c, output, pickle.HIGHEST_PROTOCOL)

with open("test.pkl", 'rb') as input_file:
    restored_c = pickle.load(input_file)
print(restored_c.my_yaml)
# 验证yaml实例的自定义配置已恢复
print(restored_c.yaml.representer.representers[str])

方案二:将YAML实例设为类属性(适用于所有实例共享同一YAML配置的场景)

如果你的类所有实例都使用相同的自定义YAML配置,可将yaml设为类属性——pickle仅序列化实例属性,不会处理类属性,自然避开序列化问题:

import pickle
from ruamel.yaml import YAML

class C:
    # 类属性:所有实例共享同一YAML实例
    yaml = YAML()
    # 在类层面添加自定义配置
    yaml.representer.add_representer(str, lambda dumper, data: dumper.represent_scalar('tag:yaml.org,2002:str', data, style='"'))
    
    def __init__(self):
        with open("test.yaml", 'r') as yamlFile:
            self.my_yaml = self.yaml.load(yamlFile)

# 测试序列化与反序列化
c = C()
with open("test.pkl", 'wb') as output:
    pickle.dump(c, output, pickle.HIGHEST_PROTOCOL)

with open("test.pkl", 'rb') as input_file:
    restored_c = pickle.load(input_file)
print(restored_c.my_yaml)
# 验证共享同一YAML实例
print(restored_c.yaml is C.yaml)

内容的提问来源于stack exchange,提问作者HawkwardSolo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 04:33:37