手把手教你用pyserial获取可用串口列表(Python3.9实测)

张开发
2026/4/16 2:04:15 15 分钟阅读

分享文章

手把手教你用pyserial获取可用串口列表(Python3.9实测)
Python串口编程实战精准获取设备列表的5种高阶方法当你把Arduino开发板插入电脑时系统通常会分配一个形如COM3或/dev/ttyUSB0的串口标识。但面对实验室里同时连接的十几块开发板如何快速锁定目标设备传统的设备管理器查看方式在自动化测试场景中显得力不从心。这就是serial.tools.list_ports模块大显身手的时候了。1. 串口检测基础架构1.1 模块导入的玄机初学者常会困惑为什么需要单独导入serial.tools.list_ports而不仅仅是import serial。这其实涉及到Python的模块加载机制# 正确导入方式必须显式导入子模块 import serial.tools.list_ports # 常见错误示例缺少tools子模块导入 import serial ports serial.tools.list_ports.comports() # 触发AttributeError底层机制Python的import系统采用惰性加载策略。import serial只会初始化顶层包而不会自动加载嵌套子模块。这种设计既节省内存又提高启动速度但也要求开发者显式导入所需子模块。1.2 基础设备扫描方案最基础的串口列表获取只需要两行代码import serial.tools.list_ports ports serial.tools.list_ports.comports() for port in ports: print(f设备: {port.device} | 描述: {port.description})典型输出示例设备: COM3 | 描述: USB Serial Device (COM3) 设备: COM5 | 描述: Arduino Uno (COM5)2. 工业级设备过滤技巧2.1 多条件复合筛选实际项目中我们往往需要根据硬件特征精准定位def find_target_device(): target_vid 0x2341 # Arduino典型VID target_pid 0x0043 # Uno典型PID target_description Arduino Uno for port in serial.tools.list_ports.comports(): # 三重条件验证 if (port.vid target_vid and port.pid target_pid and target_description in port.description): return port.device return None关键参数对照表参数类型示例值获取方式VID0x2341port.vidPID0x0043port.pid序列号954303432313port.serial_number接口号0port.interface2.2 模糊匹配进阶技巧当设备描述因驱动版本不同存在差异时正则表达式能派上大用场import re def fuzzy_match_ports(pattern): compiled re.compile(pattern, re.IGNORECASE) return [ p.device for p in serial.tools.list_ports.comports() if compiled.search(p.description) ] # 匹配所有FTDI芯片设备 ftdi_ports fuzzy_match_ports(rFTDI|Future Technology)3. 跨平台兼容性处理3.1 系统差异解决方案不同操作系统下的串口命名规则大相径庭import platform def get_os_specific_ports(): system platform.system() ports serial.tools.list_ports.comports() if system Windows: return [p for p in ports if p.device.startswith(COM)] elif system Linux: return [p for p in ports if /dev/tty in p.device] elif system Darwin: return [p for p in ports if /dev/cu. in p.device] else: raise RuntimeError(Unsupported platform)3.2 权限自动修复Linux/macOS在Unix-like系统上普通用户可能需要权限才能访问串口设备# 在Python中执行权限修复需要sudo权限 import os import serial.tools.list_ports for port in serial.tools.list_ports.comports(): if not os.access(port.device, os.R_OK | os.W_OK): os.system(fsudo chmod 666 {port.device})4. 实时设备监控系统4.1 动态端口变化检测通过轮询实现设备插拔监测import time from collections import defaultdict class PortMonitor: def __init__(self): self.last_state set() def check_changes(self): current {p.device for p in serial.tools.list_ports.comports()} added current - self.last_state removed self.last_state - current self.last_state current return added, removed monitor PortMonitor() while True: new, gone monitor.check_changes() if new: print(f新增设备: {new}) if gone: print(f移除设备: {gone}) time.sleep(1)4.2 基于事件的通知机制更高效的实现方案是结合平台特定APIimport threading import serial.tools.list_ports_windows # 平台特定实现 class PortWatcher(threading.Thread): def run(self): while True: changes serial.tools.list_ports_windows.wait_for_change() if changes[added]: print(检测到新设备插入:, changes[added])5. 企业级应用集成5.1 设备信息持久化记录import sqlite3 import datetime def log_ports_to_db(): conn sqlite3.connect(ports_inventory.db) c conn.cursor() c.execute(CREATE TABLE IF NOT EXISTS ports (timestamp TEXT, device TEXT, desc TEXT, vid INTEGER, pid INTEGER)) for port in serial.tools.list_ports.comports(): c.execute(INSERT INTO ports VALUES (?,?,?,?,?), (datetime.datetime.now(), port.device, port.description, port.vid, port.pid)) conn.commit() conn.close()5.2 自动化测试集成示例在CI/CD流水线中自动检测测试设备import pytest import serial.tools.list_ports pytest.fixture(scopesession) def target_port(): required {VID: 0x0403, PID: 0x6001} # FTDI设备 for port in serial.tools.list_ports.comports(): if all(getattr(port, k.lower()) v for k,v in required.items()): return port.device pytest.skip(测试设备未连接)在嵌入式开发中一个看似简单的串口列表获取背后隐藏着诸多工程实践细节。最近在调试多节点CAN总线系统时正是靠精确的设备过滤方案才快速定位到被错误识别为普通串口的CAN分析仪。

更多文章