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

使用pyModbusTCP先读线圈再读保持寄存器时出现NoneType下标错误

异常原因分析与解决

核心原因

报错'NoneType' object is not subscriptable本质是read_holding_registers()返回了None,代码直接取[0]触发异常。而先读线圈后出现这个问题,是因为pyModbusTCP的Client对象是状态化的,读线圈操作可能导致连接进入异常状态,后续复用该连接读保持寄存器时直接失败返回None。

具体可能的触发场景:

  • 读线圈的请求(0-34)超出PLC支持的线圈地址范围,PLC返回错误响应,导致Client连接状态异常。
  • 读线圈时出现通信超时、网络波动,Client未自动重建连接,后续请求复用失效连接。
  • pyModbusTCP 0.2.0版本存在连接复用的bug,单次请求失败后未重置连接状态。

代码里的问题点

  1. 未检查读取方法的返回值:不管是read_coils()还是read_holding_registers(),在通信失败时都会返回None,但代码直接使用返回值,没有做有效性判断。
  2. 变量名笔误:读保持寄存器的代码里存在变量名不匹配问题:定义了read__timer,但调用时用了read_erector_timer.readSingleRegister(),这会直接触发错误。
  3. 连接复用的风险:如果ReadFromModbusAddress类复用同一个Client实例,读线圈的异常会影响后续所有请求。

解决步骤

  1. 修正变量名笔误:把timer = read_erector_timer.readSingleRegister()改成timer = read__timer.readSingleRegister()。
  2. 添加返回值有效性检查:修改读取方法,先判断返回值是否为None,再进行后续操作:
def readSingleRegister(self):
    holdingRegisterData = self.ModbusClient_call.read_holding_registers(self.modbus_address)
    if holdingRegisterData is None:
        raise RuntimeError("读取保持寄存器失败")
    return holdingRegisterData[0]
def readManyCoils(self):
    coilData = self.ModbusClient_call.read_coils(self.modbus_address, self.modbus_address_read_count)
    if coilData is None:
        raise RuntimeError("读取线圈失败")
    return coilData
  1. 验证线圈地址范围合法性:确认PLC的线圈地址0-34是否存在,若超出范围,调整modbus_address_read_count参数为PLC支持的数量。
  2. 强制重建连接(针对旧版本bug):如果是pyModbusTCP 0.2.0的版本问题,可在每次读取前检查连接状态,断开后重连:
# 在ReadFromModbusAddress类中添加连接检查逻辑
def ensure_connection(self):
    if not self.ModbusClient_call.is_open():
        self.ModbusClient_call.close()
        self.ModbusClient_call.open()

# 读取前调用连接检查
def readManyCoils(self):
    self.ensure_connection()
    coilData = self.ModbusClient_call.read_coils(self.modbus_address, self.modbus_address_read_count)
    if coilData is None:
        # 尝试重连一次再读
        self.ModbusClient_call.close()
        self.ModbusClient_call.open()
        coilData = self.ModbusClient_call.read_coils(self.modbus_address, self.modbus_address_read_count)
        if coilData is None:
            raise RuntimeError("读取线圈失败")
    return coilData

内容的提问来源于stack exchange,提问作者user21051037

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 19:00:58