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

多层Ctype结构转YAML时内部结构序列化异常问题

问题描述

我用Ctypes定义了嵌套的Structure结构,将其转为Python字典后导出YAML时,内部子结构的值被序列化为Python对象格式(!!python/object/apply:_ctypes._unpickle),但直接打印该子结构的字典表示是正常的。硬编码相同内容的字典导出YAML则完全正常。

环境:Python 3.10,PyYAML 6.0

核心代码逻辑:

  • 自定义My_Structure继承自ctypes.Structure,实现as_dict()方法递归转换数组,但未处理嵌套的Structure实例
  • 嵌套结构substruct_t作为ee_struct的字段
  • 通过eeprom_t Union的get_as_dict()获取字典后用PyYAML导出

原因分析

问题出在My_Structure的__recursive_carray_get方法:该方法只判断了数组类型(通过__len__属性),但嵌套的substruct_t实例是My_Structure对象,不会触发递归转换。当调用getattr(self, field[0])获取substruct字段时,得到的是substruct_t实例而非其字典表示,PyYAML会默认将ctypes对象序列化为pickle格式,导致YAML中出现!!python/object/apply内容。

虽然打印as_dict()时看起来是字典,但实际上value对应的是substruct_t实例,只是打印时调用了__repr__显示为字典,而PyYAML序列化时会直接处理底层对象。

解决方案

修改__recursive_carray_get方法,增加对My_Structure实例的判断,递归调用其as_dict()方法;同时将ctypes基础类型转换为Python原生类型,避免残留ctypes对象:

class My_Structure(Structure):
    def __recursive_carray_get(self, value):
        # 优先处理嵌套的Structure实例
        if isinstance(value, My_Structure):
            return value.as_dict()
        # 处理数组类型
        elif hasattr(value, '__len__'):
            rtn = list()
            for i in range(value.__len__()):
                rtn.append(self.__recursive_carray_get(value.__getitem__(i)))
            return rtn
        # 处理ctypes基础类型(位域、数值等),转为Python原生类型
        else:
            return value.value if hasattr(value, 'value') else value

    def __handle_array_type__(self, type):
        return StringBetween("'", "'", str(type)).split(".")[1]
    
    def __repr__(self) -> str:
        return str(self.as_dict())

    def __str__(self) -> str:
        values = ",\n".join(f"{name}={value['value']}" for name, value in self.as_dict().items())
        return f"<{self.__class__.__name__}: {values}>"
    
    def as_dict(self) -> dict:
        return {
            field[0]: {
                'value': self.__recursive_carray_get(getattr(self, field[0])),
                'type': self.__handle_array_type__(field[1])
            }
            for field in self._fields_
        }

验证效果

修改后,substruct字段的value会被正确转换为嵌套字典,PyYAML导出时会正常序列化为普通字典结构,不再出现pickle格式的对象内容。


内容的提问来源于stack exchange,提问作者István Szekér

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 13:02:52