《从PySerial到实时读写:Python串口通信实战与高可靠封装》

309 阅读2分钟

一、背景

在物联网和工业控制领域,串口通信仍是设备交互的基石。但Python原生的pyserial库在实际项目中往往捉襟见肘——线程安全、实时读写、超时控制等问题频发。本文将带你从基础Serial调用开始,逐步构建一个支持多线程、实时数据处理的工业级串口工具类

二、PySerial基础实现

先介绍最简单最常用的串口读写实现

2.1 环境准备

pip install pyserial  # 基础库
pip install serial-tools  # 可选工具集

2.2 简单例子

import serial  
  
# 初始化连接  
serial_ = serial.Serial(  
port='COM7',  
baudrate=115200,  
timeout=2 # 读超时(秒)  
)  
  
cmd = "ls\n".encode("utf-8") # 每条命令必带换行符,表示一条命令的结束  
  
# 读取100字节  
serial_.write(cmd)  
response = serial_.read(100)  
print(response.decode("utf-8", "ignore"))  
  
# 读取一行  
serial_.write(cmd)  
response = serial_.readline()  
print(response.decode("utf-8", "ignore"))  
  
# 读取多行  
serial_.write(cmd)  
serial_.readlines()  
print(response.decode("utf-8", "ignore"))  
  
# 读取所有  
serial_.write(cmd)  
response = serial_.readall()  
print(response.decode("utf-8", "ignore"))  
  
# 必须显式关闭!  
serial_.close()

2.3 痛点分析

  1. 阻塞式读取,不能准确判断数据结束位置。
  2. 数据读写与业务逻辑高度耦合。
  3. 可靠性,易用性差,有数据丢失的可能。

三、高级封装

3.1 待解决问题清单

问题类型引发场景后果
线程阻塞长时间read()程序无响应
数据粘包高速传输协议解析失败
设备异常掉线USB接触不良进程崩溃
编码混乱中英文混合数据解码错误

串口工具核心指标.png

3.2 具体实现

3.3 核心介绍

  1. 多线程读写隔离,通过Event同步
  2. 数据缓冲设计,一直读,直到线程结束
  3. 支持check操作,检查输出中是否出现某些关键字

3.4 使用示例

from base_serial import BaseSerial  
serial_ = BaseSerial("COM10")  
# 读取到的数据输出到终端  
serial_.reader_output(True)  
  
# 输入指定命令,并获取返回  
print(serial_.write("ls", called=True, timeout=2).decode("utf-8"))  
  
# 检查日志中是否有指定关键字  
# print("检查是否有config1 : {}".format(serial_.check_log(5, *["config1"])))  
  
print("检查是否有linkerconfig:{}".format(serial_.check_log(5, *["linkerconfig"])))  
  
# 输入键值  
serial_.key_event("KEYCODE_DPAD_UP")  
serial_.key_event(19)

关键字《linkerconfig》存在的例子

acct        data_mirror      mnt          second_stage_resources
apex        debug_ramdisk    odm          storage
bin         dev              odm_dlkm     sys
bugreports  etc              oem          system
cache       init             postinstall  system_dlkm
config      init.environ.rc  proc         system_ext
d           linkerconfig     product      vendor
data        metadata         sdcard       vendor_dlkm

acct        data_mirror      mnt          second_stage_resources
apex        debug_ramdisk    odm          storage
bin         dev              odm_dlkm     sys
bugreports  etc              oem          system
cache       init             postinstall  system_dlkm
config      init.environ.rc  proc         system_ext
d           linkerconfig     product      vendor
data        metadata         sdcard       vendor_dlkm
console:/ $ 
检查是否有linkerconfig:True


console:/ $ 
Process finished with exit code 0

关键字《config1》不存在的例子

acct        data_mirror      mnt          second_stage_resources
apex        debug_ramdisk    odm          storage
bin         dev              odm_dlkm     sys
bugreports  etc              oem          system
cache       init             postinstall  system_dlkm
config      init.environ.rc  proc         system_ext
d           linkerconfig     product      vendor
data        metadata         sdcard       vendor_dlkm

acct        data_mirror      mnt          second_stage_resources
apex        debug_ramdisk    odm          storage
bin         dev              odm_dlkm     sys
bugreports  etc              oem          system
cache       init             postinstall  system_dlkm
config      init.environ.rc  proc         system_ext
d           linkerconfig     product      vendor
data        metadata         sdcard       vendor_dlkm
console:/ $ 
检查是否有config1 : False


console:/ $ 
Process finished with exit code 0

完整代码链接:github.com/WJQ6666/Ser…