从另一个类修改一个类的函数

时间:2018-06-18 06:06:14

标签: python handler socketserver pymodbus

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
    """

引发NotImplementedException(“方法未由派生类实现”)

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

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

2 个答案:

答案 0 :(得分: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

如果你想确保复制名称,文档字符串等,你可以使用`wrapps:

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

同样,您可以在代码中的任何位置执行此操作,即使在方法的中间也是如此。

如果您需要对ModbusBaseRequestHandler的一个实例进行monkeypatch,同时保持其他任何实例不受影响,您甚至可以这样做。您只需手动绑定方法:

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

如果你想调用原始方法,或者wraps,或者在其他方法等中间执行此操作,则它与上一版本基本相同。

答案 1 :(得分: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)

更多说明,here