如何在python 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.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..."
5 个回答
1
另一种我认为更符合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实例,但在这种情况下,会调用__call__方法,而不是构造函数(因为它已经是一个实例了)。
在call方法中,我明确地复制了当前的EchoHandler,并把它传给父类的构造函数,以保持“每个请求一个处理器实例”的原始逻辑。
值得一看的是SocketServer模块,以理解这里发生了什么:https://github.com/python/cpython/blob/2.7/Lib/SocketServer.py
11
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
33
很遗憾,从服务器外部直接访问处理程序并没有简单的方法。
你有两种选择可以将信息传递给 EchoHandler 实例:
- 把连接存储为服务器的一个属性(在调用
server_forever()
之前加上server.conn = conn
),然后在 EchoHandler.handler 中通过self.server.conn
来访问这个属性。 - 你可以重写服务器的
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