Подтвердить что ты не робот

С socketserver python как передать переменную в конструктор класса обработчика

Я хотел бы передать мое соединение с базой данных классу 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..."
4b9b3361

Ответ 1

К сожалению, действительно нет простого способа получить доступ к обработчикам непосредственно извне сервера.

У вас есть два варианта получения информации в экземплярах EchoHandler:

  • Сохраните соединение как свойство сервера (добавьте server.conn = conn перед вызовом server_forever()), а затем получите доступ к этому свойству в EchoHandler.handler через self.server.conn.
  • Вы можете перезаписать сервер finish_request и присвоить ему значение (вам нужно передать его конструктору EchoHandler и перезаписать EchoHandler.__ init__). Это решение far messier, и в значительной степени это требует, чтобы вы все равно сохраняли соединение на сервере.

Мой вариант наилучшего выбора:

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

Ответ 2

У Марка 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

Ответ 3

Другим способом, который, я считаю, больше pythonic, является следующее:

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 для каждого запроса, но в этом случае вместо конструктора будет вызываться метод __ вызов __, который уже является экземпляром. )

В методе вызов я явно делаю копию текущего EchoHandler и передаю его суперструктору, чтобы он соответствовал исходной логике "один экземпляр обработчика для каждого запроса".

Посмотрите на модуль SocketServer, чтобы понять, что здесь происходит: https://github.com/python/cpython/blob/2.7/Lib/SocketServer.py