如何用单个循环动态打印ctypes结构体及嵌套结构体的所有字段与值?
用单个循环(递归)遍历ctypes嵌套结构体与数组
问题描述
我用Python的ctypes定义了包含嵌套结构体与数组的多层结构体,目前需要通过多个for循环才能打印所有字段及其对应值。能否仅用一个循环实现该功能,以更高效地完成CSV文件的读写操作?
原代码
import ctypes as c class list(c.Structure): _fields_ = [('x', c.c_uint16), ('y', c.c_uint16 * 2)] class data(c.Structure): _fields_ = [('a', c.c_float), ('b', c.c_float), ('c', c.c_float)] class parameters(c.Structure): _fields_ = [('variable1', c.c_uint16), ('variable2', c.c_uint16), ('tablelist', list), ('datalist', data * 2)] a = b'\x05\x00\x14\x00\x1E\x00\x0A\x00\x0F\x00\x14\x00\x00\x40\xFA\x43\x66\x26\x16\x44\x33\x33\x48\x44\x66\x26\x96\x43\x33\x33\xC8\x43\x00\x20\xFA\x43' instance = parameters.from_buffer_copy(a)
原多循环打印输出
<__main__.parameters object at 0x00000267B1615DC0> --------------------------- variable1 5 variable2 20 tablelist <__main__.list object at 0x00000267B17848C0> datalist <__main__.data_Array_2 object at 0x00000267B17848C0> --------------------------- x 30 y <__main__.c_ushort_Array_2 object at 0x00000267B1784DC0> --------------------------- y 10 y 15 --------------------------- <__main__.data object at 0x00000267B1784DC0> a 500.5 b 600.5999755859375 c 800.7999877929688 <__main__.data object at 0x00000267B1784E40> a 300.29998779296875 b 400.3999938964844 c 500.25
解决方案:递归遍历函数
可以编写一个递归函数统一处理所有嵌套层级的结构体和数组,无需手动编写多层循环。该函数会遍历所有字段,生成带层级路径的字段名(如tablelist.x、datalist[0].a)与对应值,方便直接用于CSV读写。
实现代码
import ctypes as c import csv class list(c.Structure): _fields_ = [('x', c.c_uint16), ('y', c.c_uint16 * 2)] class data(c.Structure): _fields_ = [('a', c.c_float), ('b', c.c_float), ('c', c.c_float)] class parameters(c.Structure): _fields_ = [('variable1', c.c_uint16), ('variable2', c.c_uint16), ('tablelist', list), ('datalist', data * 2)] def traverse_struct(obj, parent_path="", result=None): if result is None: result = [] # 处理ctypes结构体 if isinstance(obj, c.Structure): for field_name, _ in obj._fields_: current_path = f"{parent_path}.{field_name}" if parent_path else field_name traverse_struct(getattr(obj, field_name), current_path, result) # 处理ctypes数组 elif hasattr(obj, '_length_') and hasattr(obj, '__getitem__'): for idx, element in enumerate(obj): current_path = f"{parent_path}[{idx}]" traverse_struct(element, current_path, result) # 处理基础数据类型 else: result.append((parent_path, obj)) return result # 测试遍历并打印 a = b'\x05\x00\x14\x00\x1E\x00\x0A\x00\x0F\x00\x14\x00\x00\x40\xFA\x43\x66\x26\x16\x44\x33\x33\x48\x44\x66\x26\x96\x43\x33\x33\xC8\x43\x00\x20\xFA\x43' instance = parameters.from_buffer_copy(a) all_fields = traverse_struct(instance) for path, value in all_fields: print(path, value) # 写入CSV文件 with open('struct_data.csv', 'w', newline='', encoding='utf-8') as f: writer = csv.writer(f) writer.writerow(['字段路径', '值']) writer.writerows(all_fields)
运行输出
variable1 5 variable2 20 tablelist.x 30 tablelist.y[0] 10 tablelist.y[1] 15 datalist[0].a 500.5 datalist[0].b 600.5999755859375 datalist[0].c 800.7999877929688 datalist[1].a 300.29998779296875 datalist[1].b 400.3999938964844 datalist[1].c 500.25
说明
- 递归逻辑:函数自动识别结构体、数组和基础类型,递归遍历所有层级,无需手动编写多层循环。
- 字段路径:生成的路径清晰展示值的层级位置,CSV读取后可直接识别数据归属。
- CSV适配:收集到的
(路径, 值)列表可直接通过csv.writer写入文件,读写流程高效统一。
内容的提问来源于stack exchange,提问作者Isaac Zaiek
相关产品推荐
相关产品推荐

