如何在Python中使用pySerial读取串口输出且无需指定字节数?
解决Serial读取动态长度返回内容的问题
你遇到的这个场景太常见了——串口设备返回的内容长度不固定,硬编码读取字节数确实既不灵活也容易丢数据。下面给你几个实用的解决方案,你可以根据自己设备的实际情况选择:
方法1:读取直到特定结束符
绝大多数串口设备会在命令返回的末尾加上固定的结束标记,比如\r\n、\n或者特定的字符序列。你可以直接用pyserial提供的read_until()方法,读取直到遇到这个结束符为止:
from time import sleep import serial ser = serial.Serial() ser.baudrate = 115200 ser.port = 'COM20' ser.open() # 注意:新版本pyserial要求write传入字节串,所以加b前缀转成bytes类型 ser.write(b"system\r") # 这里假设设备返回以\r\n结尾,你可以根据实际返回的结束符调整 result = ser.read_until(b"\r\n") # 转成字符串方便查看,编码格式如果不是utf-8可以换成设备对应的编码 print(result.decode('utf-8')) ser.close()
如果不确定设备的结束符,你可以先运行一次原代码,把返回的result打印出来,看看末尾的标记是什么,再替换到read_until()的参数里。
方法2:读取缓冲区所有可用字节
如果设备在返回完数据后会暂时停止发送,你可以先给设备一点响应时间,然后读取当前缓冲区里的所有可用字节:
from time import sleep import serial ser = serial.Serial() ser.baudrate = 115200 ser.port = 'COM20' ser.open() ser.write(b"system\r") # 延迟时间根据设备响应速度调整,比如0.1-1秒,确保设备返回完数据 sleep(0.1) # 读取缓冲区中所有可用的字节,不用硬编码长度 result = ser.read(ser.in_waiting) print(result.decode('utf-8')) ser.close()
这个方法的小缺点是需要调整延迟时间——太短可能读不全,太长又会拖慢程序,你可以多测试几次找到合适的数值。
方法3:循环读取直到超时
如果不确定结束符,也不想依赖固定延迟,你可以给串口设置超时时间,循环读取直到没有新数据返回:
from time import sleep import serial ser = serial.Serial() ser.baudrate = 115200 ser.port = 'COM20' # 设置超时时间,比如0.5秒:如果超过这个时间没有新数据,read()会返回空 ser.timeout = 0.5 ser.open() ser.write(b"system\r") result = b"" while True: # 每次读取1024字节,这个数值可以按需调整 chunk = ser.read(1024) if not chunk: # 没有新数据了,跳出循环 break result += chunk print(result.decode('utf-8')) ser.close()
这种方法适应性最强,不需要提前知道设备的返回规则,只要设备在返回完数据后会暂停发送,超时后就会自动停止读取。
最后提醒一句:新版本的pyserial对数据类型要求更严格,write()方法必须传入字节串(bytes),所以记得给你的命令字符串加上b前缀,避免出现类型错误。
内容的提问来源于stack exchange,提问作者Q.usr
相关产品推荐
相关产品推荐

