1

server.sync的 pymodbus 库中,使用了SocketServer.BaseRequestHandler,定义如下:

class ModbusBaseRequestHandler(socketserver.BaseRequestHandler):
""" Implements the modbus server protocol
This uses the socketserver.BaseRequestHandler to implement
the client handler.
"""
running = False
framer = None

def setup(self):
    """ Callback for when a client connects
    """
    _logger.debug("Client Connected [%s:%s]" % self.client_address)
    self.running = True
    self.framer = self.server.framer(self.server.decoder, client=None)
    self.server.threads.append(self)

def finish(self):
    """ Callback for when a client disconnects
    """
    _logger.debug("Client Disconnected [%s:%s]" % self.client_address)
    self.server.threads.remove(self)

def execute(self, request):
    """ The callback to call with the resulting message
    :param request: The decoded request message
    """
    try:
        context = self.server.context[request.unit_id]
        response = request.execute(context)
    except NoSuchSlaveException as ex:
        _logger.debug("requested slave does not exist: %s" % request.unit_id )
        if self.server.ignore_missing_slaves:
            return  # the client will simply timeout waiting for a response
        response = request.doException(merror.GatewayNoResponse)
    except Exception as ex:
        _logger.debug("Datastore unable to fulfill request: %s; %s", ex, traceback.format_exc() )
        response = request.doException(merror.SlaveFailure)
    response.transaction_id = request.transaction_id
    response.unit_id = request.unit_id
    self.send(response)

# ----------------------------------------------------------------------- #
# Base class implementations
# ----------------------------------------------------------------------- #
def handle(self):
    """ Callback when we receive any data
    """
    raise NotImplementedException("Method not implemented by derived class")

def send(self, message):
    """ Send a request (string) to the network
    :param message: The unencoded modbus response
    """

raise NotImplementedException("方法未由派生类实现")

当客户端连接到服务器时调用 setup(),当客户端断开连接时调用 finish()。我想在另一个使用库(pymodbus)的文件的另一个类中操作这些方法(setup()和finish()),并添加一些代码来设置和完成函数。我不打算修改库,因为它可能会在特定情况下导致奇怪的行为。

---已编辑----为了澄清,我希望 ModbusBaseRequestHandler 类中的设置函数像以前一样工作并且保持不变,但是添加其他东西,但是这个修改应该在我的代码中而不是在库中完成。

4

2 回答 2

0

它可以通过拦截器完成

from functools import wraps 

def iterceptor(func):
    print('this is executed at function definition time (def my_func)')

@wraps(func)
def wrapper(*args, **kwargs):
    print('this is executed before function call')
    result = func(*args, **kwargs)
    print('this is executed after function call')
    return result

return wrapper


@iterceptor
def my_func(n):
   print('this is my_func')
   print('n =', n)


my_func(4)

更多解释可以在这里找到

于 2018-06-24T05:26:41.547 回答
0

最简单,通常也是最好的做法是不要操作 的方法ModbusBaseRequestHandler,而是从它继承并覆盖子类中的这些方法,然后在使用基类的任何地方使用子类:

class SoupedUpModbusBaseRequestHandler(ModbusBaseRequestHandler):
    def setup(self):
        # do different stuff
        # call super().setup() if you want
        # or call socketserver.BaseRequestHandler.setup() to skip over it
        # or call neither

请注意,一个class语句只是一个普通的语句,它可以去任何其他语句可以去的任何地方,甚至是在一个方法的中间。因此,即使您需要动态创建子类,因为setup直到运行时您才知道要做什么,这也不是问题。


如果您确实需要对课程进行monkeypatch,那并不难——尽管如果您不小心,很容易搞砸。

def setup(self):
    # do different stuff
ModbusBaseRequestHandler.setup = setup

如果您希望能够调用正常的实现,则必须将其存储在某个地方:

_setup = ModbusBaseRequestHandler.setup
def setup(self):
    # do different stuff
    # call _setup whenever you want
ModbusBaseRequestHandler.setup = setup

如果要确保复制名称、文档字符串等,可以使用 `wraps:

@functools.wraps(ModbusBaseRequestHandler.setup)
def setup(self):
    # do different stuff
ModbusBaseRequestHandler.setup = setup

同样,您可以在代码中的任何位置执行此操作,甚至在方法中间。


如果您需要对其中的一个实例进行修补,ModbusBaseRequestHandler而其他任何实例都保持不变,您甚至可以这样做。您只需要手动绑定该方法:

def setup(self):
    # do different stuff
myModbusBaseRequestHandler.setup = setup.__get__(myModbusBaseRequestHandler)

如果你想调用原始方法,或者wraps它,或者在其他一些方法的中间这样做,等等,它与上一个版本基本相同。

于 2018-06-18T06:15:51.680 回答