15

我正在实现一个正在使用的 python 应用程序ThreadingTCPServer和一个BaseRequestHandler. 这样做的问题是ThreadingTCPServer似乎自动产生线程并创建处理程序的实例,调用它们的handle()函数。然而,除了使用全局变量或类变量之外,这让我无法将数据传递给处理程序,这两种变量看起来都很骇人。有没有更好的方法呢?

理想情况下,这应该是这样的:

class ThreadedTCPServer(ThreadingTCPServer):
    def process_request(self, *args, **kwargs):
        ThreadingTCPServer.process_request(self, data, *args, **kwargs)

与处理程序一样

class ThreadedTCPRequestHandler(BaseRequestHandler):
    def handle(self,data):
        #do something with data
4

3 回答 3

28

我偶然发现了同样的事情。我的解决方案如下:

class ThreadedTCPRequestHandler(SocketServer.StreamRequestHandler):
    def handle(self):
        print(self.server.mycustomdata)

class ThreadedTCPServer(SocketServer.ThreadingTCPServer):
    pass

server = ThreadedTCPServer((args.host, args.port), ThreadedTCPRequestHandler)
server.mycustomdata = 'foo.bar.z'
server.serve_forever()

RequestHandler 以服务器对象作为第三个参数调用,并保存为self.server属性,因此您可以访问它。如果您将此属性设置为可调用,您也可以轻松调用它:

def handle(self):
    mycustomdata = self.server.mycustomdata()
于 2013-11-08T23:10:33.613 回答
5

第一个答案对我有用,但我认为更改__init__方法并在构造函数中传递属性更简洁:

class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):

    def __init__(self, host_port_tuple, streamhandler, Controllers):
        super().__init__(host_port_tuple, streamhandler)
        self.Controllers = Controllers

注意构造函数中的第三个参数“Controllers”,然后在没有该参数的情况下调用 super,然后将新属性 Controllers 设置为属性 self.Controllers。类的其余部分保持不变。然后,在您的请求处理程序中,您可以使用“服务器”属性访问参数,如上所述:

def handle(self):        
    self.Controllers = self.server.Controllers
    <rest of your code>

它与上面的答案大致相同,但我觉得它更简洁一些,因为构造函数被重载,你只需在构造函数中添加你想要的属性:

server = ServerInterface.ThreadedTCPServer((HOST, PORT), ServerInterface.ThreadedTCPRequestHandler, Controllers)
于 2016-02-12T14:23:38.297 回答
2

由于handle是由您的BaseRequest子类实现的,因此它可以从自身获取数据,而无需调用者传递数据。(handle也可以是请求实例的可调用属性,例如user_datalambda——在惯用设计的 python 中通常不需要显式参数。)

查看 SocketServer 代码,finish_request将附加数据传递给BaseRequestHandler子类型构造函数应该很简单,该构造函数会将其存储在实例中handle以供使用。

于 2012-09-02T14:03:42.950 回答