清空串口缓冲区(发送/接收区)
这是最常见的需求,通常发生在以下情况:

- 在发送新命令之前,确保没有残留的旧数据干扰。
- 在开始读取新数据之前,丢弃掉之前已经处理完或无用的数据。
pyserial 的 Serial 对象提供了两个专门的方法来实现这一点:
serial.Serial.reset_input_buffer(): 清空输入缓冲区(即从设备读取到但尚未被 Python 读取的数据)。serial.Serial.reset_output_buffer(): 清空输出缓冲区(即已通过 Python 写入串口,但尚未被发送设备完全处理的数据)。
一个更彻底的、同时清空两个缓冲区的方法是:
serial.Serial.reset_output_buffer(): 重置串口,它会将所有内部缓冲区(输入和输出)清空,并将串口线(DTR - Data Terminal Ready)的状态重置为开启,这是最常用、最推荐的“清空”操作。
示例代码
import serial
import time
# --- 1. 配置串口 ---
# 请根据你的实际情况修改 'COM3' 和 9600
# 在 Linux/Mac 上可能是 '/dev/ttyUSB0' 或 '/dev/ttyACM0'
PORT = 'COM3'
BAUDRATE = 9600
try:
# 打开串口
ser = serial.Serial(PORT, BAUDRATE, timeout=1)
print(f"串口 {ser.name} 已成功打开。")
# --- 2. 清空串口(推荐方法) ---
# 在发送或接收数据之前,先重置串口,确保一个干净的通信环境
print("\n正在重置串口(清空所有缓冲区)...")
ser.reset_input_buffer() # 清空输入缓冲区
ser.reset_output_buffer() # 清空输出缓冲区
# 或者直接使用 ser.reset(),它等同于上面两行操作
# ser.reset()
print("串口已重置。")
# --- 3. 发送数据 ---
command_to_send = b'GET_DATA\n' # 发送一个命令,以 b 开头表示字节串
print(f"\n正在发送数据: {command_to_send}")
ser.write(command_to_send)
time.sleep(0.5) # 给设备一些处理时间
# --- 4. 接收数据 ---
# 在读取之前,再次清空输入缓冲区是个好习惯,以防有意外数据
ser.reset_input_buffer()
print("正在等待接收数据...")
# 读取一行数据,直到遇到换行符 '\n' 或超时
received_data = ser.readline()
if received_data:
print(f"成功接收数据: {received_data}")
else:
print("未接收到任何数据(可能已超时)。")
except serial.SerialException as e:
print(f"无法打开串口 {PORT}: {e}")
except Exception as e:
print(f"发生错误: {e}")
finally:
# --- 5. 关闭串口 ---
if 'ser' in locals() and ser.is_open:
print("\n正在关闭串口...")
ser.close()
print("串口已关闭。")
清空软件缓冲区(Python 端)
你读取的数据可能包含很多无用的前导字符(比如设备启动时的信息、调试信息等),你可能想只关心最后的有效数据。
这时,你可以在 Python 代码层面循环读取并丢弃数据,直到你找到你想要的起始标记。

示例代码:丢弃所有数据直到找到特定标记
import serial
import time
PORT = 'COM3'
BAUDRATE = 9600
START_MARKER = b'START_DATA' # 定义我们期望的数据起始标记
ser = serial.Serial(PORT, BAUDRATE, timeout=0.1) # 设置一个较短的timeout以便快速循环
try:
print("正在等待数据起始标记...")
while True:
# 读取一个字节
byte = ser.read(1)
if not byte: # 如果超时,返回空字节
continue
# 检查这个字节是否是我们标记的第一个字节
if byte == START_MARKER[0]:
# 如果是,尝试读取剩余的标记部分
marker = byte
for i in range(1, len(START_MARKER)):
next_byte = ser.read(1)
if not next_byte:
break # 超时,放弃本次匹配
marker += next_byte
if next_byte != START_MARKER[i]:
break # 不匹配,放弃
# 如果我们成功匹配了整个标记
if marker == START_MARKER:
print("找到起始标记!")
# 我们可以开始读取我们真正想要的数据了
# 读取一行
actual_data = ser.readline()
print(f"接收到有效数据: {actual_data}")
break # 退出循环
except serial.SerialException as e:
print(f"串口错误: {e}")
finally:
if ser.is_open:
ser.close()
print("串口已关闭。")
清空终端/控制台输出
有时候你可能想说的“清空”是指清空你在 Python IDE(如 PyCharm, VS Code)或命令行终端上打印的输出。
这和 pyserial 无关,是 Python 的标准操作。
示例代码
import os
import time
# 方法1:使用 os.system() 调用系统命令
# 在 Windows 上
os.system('cls')
# 在 Linux 或 macOS 上
# os.system('clear')
# 方法2:打印多行空行(跨平台,但不够“干净”)
print("\n" * 50)
# 方法3:使用 ANSI 转义码(更现代、跨平台)
# \033[2J 清屏,\033[H 光标移到左上角
print('\033[2J\033[H', end='')
print("屏幕已清空。")
总结与最佳实践
| 需求 | 推荐方法 | 说明 |
|---|---|---|
| 清空硬件缓冲区(发送/接收区) | ser.reset_input_buffer()ser.reset_output_buffer()或 ser.reset() |
最常用,在每次通信开始前或中间需要重新同步时调用,确保数据干净。ser.reset() 是最彻底的选择。 |
| 丢弃无用数据 | ser.read(数据长度) 或 ser.readline() 并不保存结果 |
在读取有效数据前,循环读取并丢弃数据,直到找到特定标记(如 b'START')。 |
| 清空软件控制台 | os.system('cls' or 'clear') 或 ANSI 转义码 |
与 pyserial 无关,用于管理你的程序输出界面。 |
核心建议:
在进行串口通信时,养成一个良好的习惯:在发送关键指令之前,先调用 ser.reset() 或至少 ser.reset_input_buffer(),这可以极大地避免因数据错位、残留数据等导致的各种奇怪问题。

