С 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..."
Ответы
Ответ 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