Python读取Arduino串口数据报UnicodeDecodeError如何解决
报错根因
偶发的UnicodeDecodeError是串口通信过程中出现了非UTF-8编码的脏数据导致的,比如Arduino上电复位阶段、USB连接抖动时会产生0xff这类无效字节,Python默认的严格解码规则碰到这类字节会直接抛出异常。
修复解码逻辑的方案
不需要大改现有代码,通过以下优化即可解决崩溃问题:
- 给解码方法添加错误处理参数,忽略或替换无效字节,避免直接报错:
用errors='ignore'直接丢弃无效字节:
也可以用x = ser.readline().decode('utf-8', errors='ignore')errors='replace'把无效字节替换为�占位符,方便感知脏数据的出现频率。 - 增加串口初始化等待逻辑,Arduino通过USB连接时会自动复位,打开串口后加2秒延迟,避免读取上电阶段的脏数据:
import serial import time ser = serial.Serial('/dev/ttyACM0', 9600) time.sleep(2) - 增加异常捕获兜底,避免偶发的串口异常导致整个程序崩溃:
完整示例代码:import serial import time import sys ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1) time.sleep(2) while True: try: line = ser.readline() if not line: continue x = line.decode('utf-8', errors='ignore').strip() if x: print(x) except Exception as e: print(f"读取异常: {e}", file=sys.stderr) continue
绕开解码的实现方案
完全可以绕开解码步骤直接提取整数,你的需求场景下更稳定:
你Arduino端用Serial.print()输出的整数本质是ASCII格式的字节串,不需要转成字符串再处理,直接对字节串做转换即可:
import serial import time ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1) time.sleep(2) while True: line = ser.readline().strip() if not line: continue try: # 直接对字节串做整数转换,完全不需要解码步骤 num = int(line) print(num) except ValueError: # 脏数据转整数失败直接跳过即可 continue
如果后续你修改Arduino代码用Serial.write()直接输出二进制格式的整数,还能进一步提升传输效率,完全避免字符编码相关的问题。
内容的提问来源于stack exchange,提问作者chaz
相关产品推荐
相关产品推荐

