在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函数像以前一样工作并保持不变,但是添加其他东西,但是这个修改应该在我的代码中完成,而不是在库中。
答案 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