You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python 3.8环境下RTU send_message间歇性失败问题求助

解决Windows下umodbus RTU随机出现ClearCommError (错误码995)问题

问题根源

错误码995(The I/O operation has been aborted because of either a thread exit or an application request.)本质是Windows系统中止了串口I/O操作,常见触发场景包括:

  • 长期持有的串口连接被系统资源回收
  • pyserial/umodbus旧版本的兼容性bug
  • USB串口设备的电源管理策略干扰
  • 串口操作超时或状态异常未被正确处理

解决方案

1. 优化串口连接生命周期管理

避免长期持有同一个串口对象,建议每次发送前重新初始化串口,发送完成后立即关闭,减少资源占用:

import serial
from umodbus.client.serial import rtu
import time

def init_serial():
    return serial.Serial(
        port="COM3",  # 替换为你的实际串口号
        baudrate=115200,
        parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        bytesize=serial.EIGHTBITS,
        timeout=10,
        write_timeout=5
    )

while True:
    ser = None
    try:
        ser = init_serial()
        rtu.send_message(msg, ser)
    except Exception as e:
        print(f"发送失败: {str(e)}")
    finally:
        if ser and ser.is_open:
            ser.close()
    time.sleep(120)

2. 升级依赖库版本

当前使用的umodbus 1.0.4和配套的pyserial可能存在Windows串口处理的bug,升级到最新稳定版:

pip install --upgrade pyserial umodbus

3. 禁用USB串口设备的电源管理

Windows可能自动关闭USB串口设备以省电,导致连接中断:

  1. 打开设备管理器,找到你的串口设备(通常在「端口(COM和LPT)」下)
  2. 右键选择「属性」→「电源管理」
  3. 取消勾选「允许计算机关闭此设备以节约电源」,点击确定

4. 异常捕获与自动恢复

针对特定错误做捕获,出现异常时自动重置串口连接,避免程序崩溃:

from umodbus.client.serial import rtu
import serial
import time

# 初始化串口
serial_port = serial.Serial(
    port="COM3",
    baudrate=115200,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS,
    timeout=10,
    write_timeout=5
)

while True:
    try:
        rtu.send_message(msg, serial_port)
    except serial.SerialException as e:
        if "ClearCommError failed" in str(e) or "995" in str(e):
            print("检测到串口异常,正在重置连接...")
            if serial_port.is_open:
                serial_port.close()
            serial_port.open()
        else:
            raise  # 其他异常正常抛出
    time.sleep(120)

5. 调整串口flush策略

原错误触发于serial_port.flush(),可以尝试手动控制flush时机,或者在umodbus的send_message调用前先检查串口状态:

# 在发送前确保串口状态正常
if not serial_port.is_open:
    serial_port.open()

# 手动flush并捕获异常
try:
    serial_port.flushOutput()
except serial.SerialException:
    serial_port.close()
    serial_port.open()

rtu.send_message(msg, serial_port)

内容的提问来源于stack exchange,提问作者주석윤

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 06:08:14