[英]With python socketserver how can I pass a variable to the constructor of the handler class
我想将我的数据库连接传递给 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 实例的信息:
server_forever()
之前添加server.conn = conn
),然后通过self.server.conn
在 EchoHandler.handler 中访问该属性。finish_request
并在那里分配值(您必须将其传递给 EchoHandler 的构造函数并覆盖 EchoHandler.__init__)。 这是一个更加混乱的解决方案,它几乎需要您无论如何都将连接存储在服务器上。我的最佳选择:
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
马克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
另一种方式,我相信更多的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实例,但在这种情况下,将调用 __call__方法而不是构造函数(它已经是一个实例。)
在调用方法中,我显式地制作了当前 EchoHandler 的副本并将其传递给超级构造函数,以符合“每个请求一个处理程序实例”的原始逻辑。
值得一看 SocketServer 模块以了解这里发生的事情: https : //github.com/python/cpython/blob/2.7/Lib/SocketServer.py
我目前正在解决同样的问题,但我使用了稍微不同的解决方案,我觉得它更好更通用(受@aramaki 启发)。
在EchoHandler
您只需要覆盖__init__
并指定自定义Creator
方法。
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"))
主要好处是,通过这种方式,您不会创建多余的实例,并且以更易于管理的方式扩展类 - 您不需要再次更改Creator
方法。
似乎您不能使用ForkingServer
来共享变量,因为当进程尝试修改共享变量时会发生写时复制。 将其更改为ThreadingServer
,您将能够共享全局变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.