Python: setup() vs __init__ () 对于套接字服务器的处理程序 class

Python: setup() vs __init__ ()for a socketserver's handler class

我正在尝试为 socketserver 定义处理程序 class。当处理程序 class 没有定义 __init__() 方法时,我的服务器工作。客户端发送的消息被写入输出window。但是,当我添加一个 __init__() 方法来声明一个 class 成员时,我的程序抛出了一个异常,因为 RequestHandlerClass 只需要一个参数,而我向它传递了四个参数。在将我的头撞到砖墙上一段时间后,我记得 BaseRequestHandler class 有一个可覆盖的 setup() 方法。我为它声明了一个覆盖并在其中声明了我的 class 成员,它起作用了。

虽然我有解决眼前问题的方法,但我想了解这一点。我不应该在请求处理程序 class 中声明我自己的 __init__() 方法吗?或者如果我应该,应该如何声明?

这是我的代码:

import socketserver
import logging
import logging.config
import json
from TWMSMessageHandler import TWMSMessageHandler

class SingleTCPHandler(socketserver.BaseRequestHandler):
    # def __init__(self):   ## causes an error 
    def setup(self):
        self.messageHandler = TWMSMessageHandler()

    # One instance per connection.  Override handle(self) to customize action.
    def handle(self):
        # self.request is the client connection
        data = self.request.recv(1024)  # clip input at 1Kb

        dataString = data.decode()
        print ("Received data: " + dataString)
        self.request.close()

class MyTCPServer(socketserver.TCPServer):

    def __init__(self, serverAddress, handler):
        super().__init__(serverAddress, handler)

    def handle_timeout(self):
        print ("No message received in {0} seconds".format(self.timeout))

if __name__ == "__main__":
    with open('TWMSHandler_log_config.json', 'rt') as f:
        config = json.load(f)
    logging.config.dictConfig(config)

    tcpServer = MyTCPServer(("127.0.0.1", 5006), SingleTCPHandler)
    tcpServer.timeout = 30

    loopCount = 0
    while loopCount < 5:
        try:
            print ("About to wait for request")
            tcpServer.handle_request()
            print ("Back from handle_request")
            loopCount = loopCount + 1
        except Exception as Value:
            print ("Oops!  " + str(Value))
            break

我假设 python 2.7,因为您没有另外指定,但是这也应该适用于 python 3.x。

如果您查看源代码 (https://hg.python.org/cpython/file/2.7/Lib/SocketServer.py#l631),您要覆盖的 BaseRequestHandler class 除了 self 之外还有 3 个参数:request, client_address, server。如果你想覆盖 __init__ 你必须与这个签名兼容,除非你也覆盖从 TCPServer 继承链中调用 __init__ 的调用站点(你不想这样做)。

由于该函数所做的只是保存状态,否则您将不得不保存自己(或通过 super 调用调用基本函数),您也可以像使用 setup是。