不修改Python底层C代码,如何扩展struct模块支持Modbus特殊浮点格式?
无需修改Python底层实现自定义格式解析
可以实现,不用改动struct模块的C底层代码,核心思路是封装一个兼容struct调用风格的自定义解析函数,拆分并分别处理标准格式和你的特殊浮点格式,最后合并结果。
实现步骤
- 拆分输入的格式字符串,识别自定义的
r字符,记录它们的位置和对应的字节偏移。 - 先解析所有标准格式部分(如
H、I等),得到基础结果列表。 - 对每个
r对应的4字节数据段执行寄存器交换(前两字节与后两字节互换),再用struct.unpack(">f")解析为浮点值,插入到结果列表的对应位置。 - 返回最终的元组,和
struct.unpack的输出格式一致。
完整代码示例
import struct def unpack_modbus(fmt, data): standard_fmt = [] custom_positions = [] byte_idx = 0 result_template = [] # 遍历格式字符串,拆分标准格式和自定义格式 for char in fmt: if char == 'r': # 记录自定义浮点的位置和字节起始索引 custom_positions.append((len(result_template), byte_idx)) result_template.append(None) byte_idx += 4 # 特殊浮点占2个寄存器=4字节 else: standard_fmt.append(char) result_template.append(None) # 累加当前标准格式的字节数 byte_idx += struct.calcsize(char) # 解析所有标准格式部分 standard_results = list(struct.unpack(''.join(standard_fmt), data)) std_idx = 0 # 填充标准结果到模板 for i in range(len(result_template)): if result_template[i] is None and (i, byte_idx) not in [pos for pos, _ in custom_positions]: result_template[i] = standard_results[std_idx] std_idx += 1 # 处理自定义特殊浮点 for pos, offset in custom_positions: # 取出4字节并交换前后寄存器块 swapped_bytes = data[offset+2:offset+4] + data[offset:offset+2] float_val = struct.unpack(">f", swapped_bytes)[0] result_template[pos] = float_val return tuple(result_template) # 测试场景:6个无符号短整型 + 1个特殊浮点 test_data = b'\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x03\x04\x01\x02' parsed = unpack_modbus(">HHHHHHr", test_data) print(parsed) # 输出示例:(1, 2, 3, 4, 5, 6, 1.0842021724855044e-19) # 注:1.0842021724855044e-19对应大端字节01 02 03 04解析的浮点值
额外说明
- 这个函数完全兼容struct的格式语法(包括字节序前缀如
>),你可以像用struct.unpack一样传入格式字符串。 - 如果后续需要添加其他自定义格式字符,只需要在遍历格式字符串的逻辑中增加对应分支,扩展成本极低。
内容的提问来源于stack exchange,提问作者Nick Muise
相关产品推荐
相关产品推荐

