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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 05:27:02