如何通过pyserial强制释放串口?解决程序崩溃后串口锁定问题
解决Python串口程序崩溃后串口锁定的问题
一、崩溃前确保串口自动释放
这是最稳妥的方案,通过Python的异常处理机制,保证无论程序正常结束还是意外崩溃,串口资源都能被释放:
使用
try...finally块
无论代码是否抛出异常,finally块中的代码都会执行,适合包裹核心串口操作逻辑:import serial ser = serial.Serial('/dev/ttyUSB0', 9600) try: # 你的串口业务逻辑 while True: data = ser.readline() print(data.decode('utf-8').strip()) finally: if ser.is_open: ser.close() print("串口已安全释放")利用上下文管理器
with
PySerial的Serial类支持上下文管理器语法,退出with块时会自动调用close(),写法更简洁:import serial with serial.Serial('/dev/ttyUSB0', 9600) as ser: # 你的串口业务逻辑 while True: data = ser.readline() print(data.decode('utf-8').strip()) # 退出with块后,串口自动关闭,无需手动调用close()全局捕获未处理异常
针对无法提前预判的异常,可以通过sys.excepthook全局捕获,在程序崩溃前执行串口释放:import serial import sys ser = None def crash_handler(exc_type, exc_value, exc_traceback): global ser if ser and ser.is_open: ser.close() print("程序崩溃,已释放串口资源") # 调用默认异常处理逻辑,保证错误信息正常输出 sys.__excepthook__(exc_type, exc_value, exc_traceback) sys.excepthook = crash_handler # 初始化串口并执行业务逻辑 ser = serial.Serial('/dev/ttyUSB0', 9600) # 你的串口操作代码
二、启动时强制释放指定串口
如果程序已经崩溃导致串口被锁定,PySerial本身没有直接的强制释放API,但可以通过操作系统层面的命令,在代码启动前清理占用串口的进程(树莓派基于Linux,适用以下方法):
- 通过
lsof和kill命令清理进程
编写Python代码调用系统命令,查找并终止占用目标串口的进程:
注意:运行这段代码需要足够权限(比如用import subprocess import serial def force_release_serial(port): try: # 查找占用串口的进程PID pids = subprocess.check_output(["lsof", "-t", port]).decode().strip().split('\n') for pid in pids: if pid: subprocess.run(["kill", "-9", pid], check=True) print(f"已强制释放串口 {port}") except subprocess.CalledProcessError: # 串口未被占用,无需操作 print(f"串口 {port} 未被占用") # 启动前先释放串口 force_release_serial('/dev/ttyUSB0') # 再初始化串口 ser = serial.Serial('/dev/ttyUSB0', 9600)sudo执行Python脚本),否则可能无法终止进程。
额外注意事项
- 避免使用
kill -9强制终止程序:这种情况下Python的异常处理机制无法触发,只能靠启动时的清理逻辑解决。 - 检查串口权限:确保当前用户对
/dev/tty*设备有读写权限,可通过sudo usermod -a -G dialout $USER添加用户到dialout组。
内容的提问来源于stack exchange,提问作者Alexis R Devitre
相关产品推荐
相关产品推荐

