Python Serial Read终极指南:从零开始掌握串口数据读取(附代码+避坑)
** 还在为Python读取串口数据发愁?本文手把手教你使用pyserial库,解决卡顿、乱码、数据丢失等常见难题,并提供项目级实战案例。

(Meta Description)
想学习如何用Python读取串口数据吗?本文是您最全面的Python Serial Read教程,我们将深入讲解pyserial库的安装、配置、数据读取方法(阻塞/非阻塞),并提供完整代码示例,助您轻松解决数据读取中的常见问题,立即上手串口通信项目!
引言:为什么Python Serial Read如此重要?
在物联网、嵌入式系统开发、工业自动化以及各类硬件交互项目中,串口通信(Serial Communication)是一种稳定、可靠且广泛使用的数据传输方式,而Python,凭借其简洁的语法和强大的库支持,成为了连接硬件与上层应用的首选语言。
“Python serial read”是无数工程师和爱好者在百度搜索框中输入的关键词,无论你是想读取Arduino传感器的数据,还是与PLC进行通信,掌握Python串口读取都是一项必备技能,本文将带你彻底搞懂pyserial,让你不再为“读不到数据”、“数据乱码”等问题而烦恼。
第一步:环境准备 - 安装Pyserial库
pyserial是Python中最流行、功能最全面的串口通信库,在开始之前,我们需要先安装它。

打开你的命令行工具(CMD、PowerShell或Terminal),执行以下命令:
pip install pyserial
安装完成后,你就可以在Python脚本中导入并使用它了。
import serial
【SEO小贴士】:在文章开头就解决用户的第一个实际问题——“怎么安装?”,能快速建立信任感,降低跳出率。
第二步:核心配置 - 打开并配置串口
读取数据的第一步是“打开”串口,这就像打开一扇门,你需要知道门的地址(串口号)以及如何使用这扇门(波特率、数据位等参数)。

查找可用串口
在连接设备前,最好先确认你的电脑上有哪些串口可用。
import serial.tools.list_ports
# 列出所有可用串口
ports = serial.tools.list_ports.comports()
print("可用串口列表:")
for port in ports:
print(f"设备: {port.device}, 描述: {port.description}, 制造商: {port.manufacturer}")
运行这段代码,你将看到类似 COM3 或 /dev/ttyUSB0 的输出,这就是你的设备地址。
打开并配置串口
serial.Serial() 是核心函数,用于打开并配置一个串口连接。
import serial
# --- 配置参数 ---
PORT = 'COM3' # Windows系统使用 'COMx',Linux/macOS使用 '/dev/ttyUSBx' 或 '/dev/tty.SLAB_USBtoUART'
BAUDRATE = 9600 # 波特率,必须与发送端设备设置一致
BYTESIZE = serial.EIGHTBITS # 数据位
PARITY = serial.PARITY_NONE # 校验位
STOPBITS = serial.STOPBITS_ONE # 停止位
TIMEOUT = 1 # 超时时间(秒)
try:
# 创建串口对象
ser = serial.Serial(
port=PORT,
baudrate=BAUDRATE,
bytesize=BYTESIZE,
parity=PARITY,
stopbits=STOPBITS,
timeout=TIMEOUT
)
if ser.is_open:
print(f"串口 {ser.name} 打开成功!")
# ... 在这里进行数据读取 ...
# 操作完成后,务必关闭串口
ser.close()
print("串口已关闭。")
except serial.SerialException as e:
print(f"无法打开串口 {PORT}: {e}")
【关键参数解释】
port: 串口号,这是最重要的参数,务必写对。baudrate(波特率): 数据传输速率,如9600,115200。必须与你的硬件设备保持一致!timeout(超时): 这是一个极其重要的参数,它决定了read()方法等待数据的时间。timeout=0: 非阻塞模式,read()会立即返回,读取到多少数据就返回多少。timeout=1: 阻塞模式,read()最多等待1秒,如果1秒内没有数据,则返回空字节。这是最常用和推荐的设置。timeout=None: 永久阻塞模式,read()会一直等待,直到有数据到达。请谨慎使用,可能导致程序卡死。
第三步:数据读取 - 三种核心方法
串口配置好了,现在终于到了最核心的“读取”环节。pyserial提供了三种主要的读取方法,适用于不同的场景。
ser.read(size=1) - 读取指定字节数
这是最基础的读取方法,它会从串口缓冲区中读取指定size数量的字节。
if ser.is_open:
# 读取1个字节
byte_data = ser.read(1)
print(f"读取到1个字节: {byte_data}, 类型: {type(byte_data)}")
# 读取10个字节
ten_bytes = ser.read(10)
print(f"读取到10个字节: {ten_bytes}")
适用场景:当你确切知道每次数据包的固定大小时,例如读取一个16位的传感器数据。
ser.readline() - 读取一行数据
readline()会持续读取,直到遇到换行符(\n)或回车符(\r)为止,然后返回整行数据。
注意:发送端的数据必须包含换行符,否则readline()会一直阻塞(根据timeout设置)。
if ser.is_open:
# 假设发送端发送 "Hello World!\n"
line_data = ser.readline()
print(f"读取到一行数据: {line_data}")
# 如果数据是文本,记得解码
decoded_line = line_data.decode('utf-8').strip()
print(f"解码后的文本: {decoded_line}")
适用场景:与人机交互终端(如串口助手)通信,或者发送端以文本行形式发送数据时。
ser.readall() - 读取所有可用数据
readall()会读取串口缓冲区中所有当前可用的数据,然后返回。
if ser.is_open:
# 假设缓冲区有 "abc" 和 "123"
all_data = ser.readall()
print(f"读取到所有数据: {all_data}")
适用场景:较少使用,通常用于一次性读取所有遗留数据,或在非阻塞模式下快速清空缓冲区。
第四步:实战案例 - 实时读取并解析传感器数据
理论讲完了,让我们来一个实战项目,假设我们有一个通过串口持续发送温度数据的传感器,数据格式为:TEMP:25.6\n。
我们的目标是:实时读取数据,提取出温度值,并在控制台打印。
import serial
import time
# --- 串口配置 ---
PORT = 'COM3'
BAUDRATE = 9600
try:
ser = serial.Serial(PORT, BAUDRATE, timeout=1)
print(f"正在从 {ser.name} 读取数据...")
while True:
if ser.in_waiting > 0: # 检查缓冲区是否有数据
# 读取一行
line = ser.readline()
try:
# 解码为字符串并去除首尾空白字符
decoded_line = line.decode('utf-8').strip()
# 检查是否是我们期望的数据格式
if decoded_line.startswith("TEMP:"):
# 提取温度值
temp_str = decoded_line.split(":")[1]
temperature = float(temp_str)
print(f"当前温度: {temperature} °C")
except UnicodeDecodeError:
print(f"接收到无法解码的数据: {line}")
except ValueError:
print(f"数据格式错误,无法转换为浮点数: {decoded_line}")
except IndexError:
print(f"数据格式不正确: {decoded_line}")
# 避免CPU空转
time.sleep(0.1)
except serial.SerialException as e:
print(f"串口错误: {e}")
finally:
if 'ser' in locals() and ser.is_open:
ser.close()
print("串口已关闭。")
代码解析:
- 我们使用一个
while True循环来持续监听串口。 ser.in_waiting > 0是一个高效的非阻塞检查,它告诉我们缓冲区里是否有新数据,避免了无谓的read()调用。- 我们用
try-except块来优雅地处理可能发生的错误,如数据乱码(解码错误)或数据格式不正确(索引错误、转换错误)。 time.sleep(0.1)让程序稍微“休息”一下,防止CPU占用率过高。
第五步:常见问题与解决方案 (FAQ)
Q1: 为什么我读取的数据是乱码,或者完全读不到?
A: 这是最常见的问题,通常由以下几个原因造成:
- 串口号错误:再次检查
list_ports的输出,确保PORT变量设置正确。 - 波特率不匹配:这是头号杀手! 确认你的设备(如Arduino、ESP32)的代码中设置的
Serial.begin()的波特率与Python脚本中的BAUDRATE完全一致。 - 设备未连接或未供电:检查硬件连接线和设备电源。
- 权限问题 (Linux/macOS):在Linux或macOS上,普通用户可能没有权限访问串口,尝试使用
sudo运行你的Python脚本,或将用户添加到dialout组。sudo usermod -a -G dialout $USER # 然后需要重新登录或重启系统
Q2: 为什么我的程序会卡在 ser.readline() 或 ser.read() 上?
A: 这是因为timeout设置不当。
- 如果
timeout设置得太大或为None,而发送端又没有按时发送数据或发送格式不正确(如缺少换行符),程序就会一直等待。 - 解决方案:将
timeout设置为一个合理的值,如1(秒),如果1秒内没有数据,函数会返回,你的程序可以继续执行其他逻辑。
Q3: 如何处理数据丢失的问题?
A: 数据丢失通常发生在读取速度跟不上数据发送速度时。
- 增加读取频率:在
while循环中减少time.sleep()的时间,或者使用更高效的读取逻辑。 - 增大缓冲区:
pyserial的缓冲区大小是有限的,如果数据量极大且密集,可以考虑在应用层实现自己的数据缓冲队列。 - 优化发送端:如果可能,让发送端降低发送频率,或发送更小的数据包。
总结与展望
恭喜你!现在你已经从零开始,掌握了Python串口数据读取的核心技能,我们回顾一下今天的关键点:
- 安装:使用
pip install pyserial。 - 配置:使用
serial.Serial()正确配置端口、波特率等参数,timeout至关重要。 - 读取:根据场景选择
read(size)、readline()或readall()。 - 实战:通过一个实时读取传感器数据的案例,将理论付诸实践。
- 排错:学会解决“读不到”、“乱码”、“卡死”等常见问题。
串口通信是连接软件与物理世界的桥梁,掌握了python serial read,你就为探索更广阔的物联网和嵌入式开发领域打下了坚实的基础,你可以尝试将读取到的数据存入数据库、绘制成动态图表,或者通过Web界面进行展示。
【行动号召】 现在就动手,连接你的第一个串口设备,用Python读取它的数据吧!如果在实践中遇到任何问题,欢迎在评论区留言讨论。
#Python #串口通信 #pyserial #SerialRead #物联网 #嵌入式开发 #硬件编程 #Python教程
