我有这样的代码:
class SingleTCPHandler(SocketServer.BaseRequestHandler):
""" One instance per connection. """
def handle(self):
data = Net.recv_from_socket(self.request)
GUI.run(str("RECV'd message: %s" % data))
class SimpleServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
def __init__(self, server_address, RequestHandlerClass):
SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass)
但我不想使用全局变量 GUI 来包含我在服务器收到消息时要调用的函数。相反,我想向 SingleTCPHandler 类发送 GUI 对象,这样它就可以在本地调用函数,而不是引用全局变量。
想法?对 python 有点陌生...
请您参考如下方法:
将您的处理程序更改为
class SingleTCPHandler(SocketServer.BaseRequestHandler):
""" One instance per connection. """
def __init__(self, callback, *args, **keys):
self.callback = callback
SocketServer.BaseRequestHandler.__init__(self, *args, **keys)
def handle(self):
data = Net.recv_from_socket(self.request)
self.callback(data)
稍后(您创建 TCP 服务器的地方):
def show_message_box(data):
GUI.run(str("RECV'd message: %s" % data))
def handler_factory(callback):
def createHandler(*args, **keys):
return ThreadedTCPRequestHandler(callback, *args, **keys)
return createHandler
server = ThreadedTCPServer((HOST, PORT), handler_factory(show_message_box))
解释:
1) handler_factory 被调用了应该被调用的回调。
2) handler_factory 创建了一个名为 createHandler 的新函数。这个功能会交给ThreadedTCPServer。它会在需要创建新处理程序时调用它。
3) 调用时,它会创建您的 ThreadedTCPRequestHandler 并将回调参数(在本例中为 show_message_box)移交给存储它的 ThreadedTCPRequestHandler.init。这背后的“魔法”被称为“闭包”。 IE。您可以从内部函数 createHandler 中的外部函数 handler_factory 访问回调参数。 Google 搜索“closure python”,您会得到一些很好的解释。
4) 当最终调用 handle() 时,它调用 self.callback(data)。由于 self.callback 是 show_message_box,show_message_box(data) 将被有效调用。
还有一些更简短的表达方式:
def my_callback():
print 'Hello'
server = ThreadedTCPServer((HOST, PORT), lambda *args, **keys: ThreadedTCPRequestHandler(my_callback, *args, **keys))
会工作,就像
def my_callback():
print 'Hello'
import functools
server = ThreadedTCPServer((HOST, PORT), functools.partial(ThreadedTCPRequestHandler, my_callback))
我不知道你的具体用例,但如果你需要用套接字做更多的事情,你可能想看看 http://www.twistedmatrix.com (流行的 python 网络包)。您还应该意识到很多 GUI 系统不喜欢从多个线程同时运行,因此您需要注意这一点。
