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

子类实例化及线程调用方法报错求助(Modbus/AttributeError)

问题分析与解决方案

错误原因拆解

  1. AttributeError: 'ModbusTcpClient' object has no attribute 'modbus'
    你直接调用Temperature_Controll2.temp_controll这个未绑定的类方法作为线程目标,还把ModbusClient实例当成第一个参数传入。但实例方法的第一个参数self必须是Temperature_Controll2的实例,这里self被错误赋值为ModbusClient对象,它自然没有modbus属性。

  2. AttributeError: 'str' object has no attribute 'database_reading'
    本质还是self参数传错了:线程参数args=(client, 'get')会让temp_controll的self接收client、value接收'get'。当调用self.database_reading()时,要么client没有这个方法,要么参数顺序错误导致self变成了字符串'get'——核心问题都是没有正确传入类实例作为self。

另外代码还有几个隐性问题:

  • Temperature_Controll2的__init__中,super调用的类名拼写错误(写成了Temperature_Controll)
  • Echo的database_reading方法定义缺少冒号
  • 创建t1线程时,target=server.serveforever()是直接执行方法而非传入方法对象,会导致主线程阻塞
  • Temperature_Controll2继承自Echo,但Echo的__init__需要4个参数,你只传了client,会触发参数不匹配错误

修正后的代码

import threading
import time
import logging
from pymodbus.client import ModbusClient
from SimpleWebSocketServer import SimpleWebSocketServer, WebSocket
from functools import partial

# 假设HOST、PORT、PORTNUM已定义
HOST = "127.0.0.1"
PORT = 502
PORTNUM = 8000

class Echo(WebSocket):
    def __init__(self, client, server, sock, address):
        super().__init__(server, sock, address)
        self.modbus = client

    def database_reading(self):  # 补充缺失的冒号
        # 替换为你的实际业务逻辑
        data = "sample_sensor_data"
        print(f"读取数据库数据: {data}")
        return data


class Temperature_Controll2(Echo):
    def __init__(self, client):
        # 由于Echo是WebSocket子类,需要传入父类要求的参数,这里用None作为占位
        super().__init__(client, server=None, sock=None, address=None)
        # 父类已经初始化了self.modbus,这里可以省略重复赋值
    
    def temp_controll(self, value):
        while True:
            print("=== 温度控制循环运行中 ===")
            try:
                rp = self.modbus.read_coils(524, 0x1)
                print(f"读取线圈状态: {rp.bits[0]}")
            except Exception as e:
                print(f"Modbus读取失败: {str(e)}")
            
            self.database_reading()
            time.sleep(1)  # 添加休眠,避免CPU占用过高


def main():
    logging.basicConfig(level=logging.INFO)
    with ModbusClient(host=HOST, port=PORT) as client:
        if not client.connect():
            print("Modbus连接失败")
            return
        time.sleep(0.01)
        print(f"WebSocket服务器运行在端口 {PORTNUM}")
        server = SimpleWebSocketServer('', PORTNUM, partial(Echo, client))
        
        # 正确步骤:先创建子类实例,再传入绑定好实例的方法
        control_instance = Temperature_Controll2(client)
        t2 = threading.Thread(target=control_instance.temp_controll, args=('get',))
        t2.daemon = True  # 设置为守护线程,主程序退出时自动终止
        t2.start()
        
        try:
            # 注意:target传入方法对象,不要加括号,否则会直接在主线程执行
            t1 = threading.Thread(target=server.serveforever)
            t1.start()
            t1.join()  # 等待WebSocket线程结束
        finally:
            server.close()
            print("服务器已关闭")

if __name__ == "__main__":
    main()

关键修正说明

  1. 正确实例化子类:先创建Temperature_Controll2的实例,再将绑定了实例的temp_controll方法作为线程目标,这样self会自动指向类实例,无需手动传入。
  2. 修正父类调用:super().__init__传入父类要求的所有参数(用None作为占位,因为单独运行控制逻辑不需要WebSocket的连接资源)。
  3. 线程目标修正:server.serveforever不要加括号,否则会直接在主线程执行,导致程序阻塞。
  4. 添加异常处理与休眠:捕获Modbus读取错误避免循环崩溃,添加休眠降低CPU占用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 05:42:08