使用python socketserver,如何将变量传递给处理程序类的构造函数

使用python socketserver,如何将变量传递给处理程序类的构造函数,python,python-2.7,socketserver,Python,Python 2.7,Socketserver,我想将我的数据库连接传递给EchoHandler类,但是我不知道如何做,也不知道如何访问EchoHandler类 class EchoHandler(SocketServer.StreamRequestHandler): def handle(self): print self.client_address, 'connected' if __name__ == '__main__': conn = MySQLdb.connect (host = "10.0.0

我想将我的数据库连接传递给EchoHandler类,但是我不知道如何做,也不知道如何访问EchoHandler类

class EchoHandler(SocketServer.StreamRequestHandler): def handle(self): print self.client_address, 'connected' if __name__ == '__main__': conn = MySQLdb.connect (host = "10.0.0.5", user = "user", passwd = "pass", db = "database") SocketServer.ForkingTCPServer.allow_reuse_address = 1 server = SocketServer.ForkingTCPServer(('10.0.0.6', 4242), EchoHandler) print "Server listening on localhost:4242..." try: server.allow_reuse_address server.serve_forever() except KeyboardInterrupt: print "\nbailing..." 类EchoHandler(SocketServer.StreamRequestHandler): def句柄(自身): 打印self.client_地址“已连接” 如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu': conn=MySQLdb.connect(host=“10.0.0.5”,user=“user”,passwd=“pass”,db=“database”) SocketServer.ForkingCpserver.allow_reuse_address=1 server=SocketServer.forkingcpserver(('10.0.0.6',4242),EchoHandler) 打印“本地主机上的服务器侦听:4242…” 尝试: server.allow\u重用\u地址 服务器。永远为您服务() 除键盘中断外: 打印“\n行李…”
不幸的是,实际上没有一种简单的方法可以直接从服务器外部访问处理程序

您有两个选项来获取EchoHandler实例的信息:

  • 将连接存储为服务器的属性(在调用
    server\u forever()
    之前添加
    server.conn=conn
    ),然后通过
    self.server.conn
    访问EchoHandler.handler中的该属性
  • 您可以覆盖服务器的
    finish\u请求
    并在那里分配值(您必须将其传递给EchoHandler的构造函数并覆盖EchoHandler.\uuuuu init\uuuuuu)。这是一个非常混乱的解决方案,它几乎要求您将连接存储在服务器上
  • 我选择您的最佳选择:

    class EchoHandler(SocketServer.StreamRequestHandler):
        def handle(self):
            # I have no idea why you would print this but this is an example
            print( self.server.conn );
            print self.client_address, 'connected'
    
    if __name__ == '__main__':
        SocketServer.ForkingTCPServer.allow_reuse_address = 1
    
        server = SocketServer.ForkingTCPServer(('10.0.0.6', 4242), EchoHandler)
        server.conn = MySQLdb.connect (host = "10.0.0.5", 
                         user = "user", passwd = "pass", db = "database")
        # continue as normal
    

    Mark T在python列表归档中有以下几点要说

    在处理程序类中,self.server引用服务器对象,因此子类 服务器和重写init以获取任何其他服务器参数 并将它们存储为实例变量

    
    import SocketServer
    
    class MyServer(SocketServer.ThreadingTCPServer):
    
        def __init__(self, server_address, RequestHandlerClass, arg1, arg2):
            SocketServer.ThreadingTCPServer.__init__(self, 
                                                     server_address, 
                                                     RequestHandlerClass)
            self.arg1 = arg1
            self.arg2 = arg2
    
    
    class MyHandler(SocketServer.StreamRequestHandler):
    
        def handle(self):
            print self.server.arg1
            print self.server.arg2
    
    

    另一种方法,我认为更像是python,是做以下事情:

    class EchoHandler(SocketServer.StreamRequestHandler):
      def __init__(self, a, b):
        self.a = a
        self.b = b
    
      def __call__(self, request, client_address, server):
        h = EchoHandler(self.a, self.b)
        SocketServer.StreamRequestHandler.__init__(h, request, client_address, server)
    
    现在,您可以将处理程序的实例提供给TCPServer:

    SocketServer.ForkingTCPServer(('10.0.0.6', 4242), EchoHandler("aaa", "bbb"))
    
    TCPServer通常会为每个请求创建一个新的EchoHandler实例,但在这种情况下,将调用\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>方法,而不是

    调用方法中,我显式复制当前EchoHandler并将其传递给超级构造函数,以符合“每个请求一个处理程序实例”的原始逻辑


    值得一看SocketServer模块,以了解这里发生了什么:

    我目前正在解决相同的问题,但我使用了稍微不同的解决方案,我觉得它稍微好一些,更通用一些(受@aramaki的启发)

    EchoHandler
    中,您只需覆盖
    \uuuu init\uuuu
    并指定自定义
    创建者
    方法

    class EchoHandler(SocketServer.StreamRequestHandler):
        def __init__(self, request, client_address, server, a, b):
            self.a = a
            self.b = b
            # super().__init__() must be called at the end
            # because it's immediately calling handle method
            super().__init__(request, client_address, server)
    
        @classmethod
        def Creator(cls, *args, **kwargs):
            def _HandlerCreator(request, client_address, server):
                cls(request, client_address, server, *args, **kwargs)
            return _HandlerCreator
    
    然后,您可以调用
    Creator
    方法并传递所需的任何内容

    SocketServer.ForkingTCPServer(('10.0.0.6', 4242), EchoHandler.Creator(0, "foo"))
    

    主要的好处是,通过这种方式,您不会创建任何超出需要的实例,并且您以更易于管理的方式扩展了类-您不需要再次更改
    创建者
    方法。

    为什么不
    super()。\uu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu(…)
    而改为
    MyServer中。\uuuuu init“老式”类。必须以这种方式调用超级构造函数。请参见此处:@ShivangiSingh可能最好发布一个问题。然后我们可以查看您的代码。