我想将我的数据库连接传递给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..."
答案 0 :(得分:25)
不幸的是,实际上没有一种简单的方法可以直接从服务器外部访问处理程序。
您有两种方法可以获取EchoHandler实例的信息:
server.conn = conn
之前添加server_forever()
),然后通过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
答案 1 :(得分:9)
Mark T在python list archive上有以下说法
在处理程序类中,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
答案 2 :(得分:1)
另一种方式,我相信更多的pythonic,是做以下事情:
^
您现在可以将处理程序的实例提供给TCPServer:
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通常会为每个请求创建一个新的 EchoHandler 实例,但在这种情况下,将调用 __ call __ 方法而不是构造函数(它已经是一个实例。 )
在调用方法中,我显式创建了当前EchoHandler的副本,并将其传递给超级构造函数,以符合“每个请求一个处理程序实例”的原始逻辑。
值得一看的是SocketServer模块,以了解这里发生的事情:https://github.com/python/cpython/blob/2.7/Lib/SocketServer.py
答案 3 :(得分:1)
似乎您不能使用 ForkingServer
来共享变量,因为当进程尝试修改共享变量时会发生写时复制。
将其更改为 ThreadingServer
,您将能够共享全局变量。
答案 4 :(得分:0)
我目前正在解决相同的问题,但是我使用的解决方案略有不同,我觉得它更好一些,也更通用(受@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
方法。