Python Serial读取结构化串口数据:如何提取目标数值?
解决思路
步骤1:清理ANSI控制码
原始字节串包含大量ANSI控制序列(清屏、光标定位指令,以\x1b[开头),需要先移除这些无效内容。用正则表达式可以高效匹配并替换:
import re raw_bytes = b'\x1b[2J\x1b[1;1fI Source:\x1b[2;1fI Limit:\x1b[3;1fV Source:\x1b[4;1fV Min:\x1b[5;1fmA Hours:\x1b[1;12f 0.000\x1b[2;12f 0.010\x1b[3;12f 0.000\x1b[4;12f 2.000\x1b[5;12f 0.00' # 转成字符串 raw_str = raw_bytes.decode('utf-8') # 移除所有ANSI控制码 clean_str = re.sub(r'\x1b\[[0-9;]*[a-zA-Z]', '', raw_str)
执行后clean_str会得到和PuTTY一致的内容:I Source:I Limit:V Source:V Min:mA Hours: 0.000 0.010 0.000 2.000 0.00。
步骤2:提取数值数据
从清理后的字符串中提取所有小数格式的数值,同样用正则匹配:
# 匹配所有带小数的数值(兼容前导空格) num_str_list = re.findall(r'\s*(\d+\.\d+)', clean_str) # 转换为浮点数,用于后续运算、绘图 float_values = [float(v.strip()) for v in num_str_list]
最终float_values会得到[0.0, 0.01, 0.0, 2.0, 0.0],直接满足记录和运算需求。
备选方案:固定格式直接提取
如果串口输出格式完全固定(数值始终在\x1b[*;12f指令后),可以跳过清理步骤,直接分割提取:
parts = raw_str.split('\x1b[') float_values = [] for part in parts: if '12f' in part: # 提取光标定位指令后的数值 num_str = part.split('12f')[1].strip() float_values.append(float(num_str))
该方法效率更高,适合格式长期稳定的场景。
注意事项
- 确认串口数据编码,若设备使用非UTF-8编码(如GBK),需调整
decode参数。 - 若数值可能出现整数、负数,修改正则表达式为
r'\s*(-?\d+\.?\d*)'即可兼容。
内容的提问来源于stack exchange,提问作者mognic
相关产品推荐
相关产品推荐

