在python TCP服务器中为handle()添加功能的正确方法?
我有这样的代码:在python TCP服务器中为handle()添加功能的正确方法?,python,Python,我有这样的代码: 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(S
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处理器工厂
2处理器\u工厂创建一个名为createHandler的新函数。此函数将移交给ThreadedTCServer。它在需要创建新的处理程序时调用它
3调用时,它会创建ThreadedTCRequestHandler,并将回调参数(在本例中为show_message_框)交给ThreadedTCRequestHandler.init,后者存储该参数。这背后的魔力叫做闭包。也就是说,您可以从内部函数createHandler中的外部函数处理程序工厂访问回调参数。谷歌搜索闭包python,你会得到一些很好的解释
4当句柄最终被调用时,它调用self.callbackdata。由于self.callback是show_message_box,因此show_message_boxdata将被有效调用
也有一些简短的表达方式:
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))
我不知道您的具体用例,但如果您需要对套接字做更多的工作,您可能想看看流行的python网络包。您还应该知道,许多GUI系统不喜欢从多个线程同时运行,因此您需要注意这一点。将处理程序更改为
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处理器工厂
2处理器\u工厂创建一个名为createHandler的新函数。此函数将移交给ThreadedTCServer。它在需要创建新的处理程序时调用它
3调用时,它会创建ThreadedTCRequestHandler,并将回调参数(在本例中为show_message_框)交给ThreadedTCRequestHandler.init,后者存储该参数。这背后的魔力叫做闭包。也就是说,您可以从内部函数createHandler中的外部函数处理程序工厂访问回调参数。谷歌搜索闭包python,你会得到一些很好的解释
4当句柄最终被调用时,它调用self.callbackdata。由于self.callback是show_message_box,因此show_message_boxdata将被有效调用
也有一些简短的表达方式:
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))
我不知道您的具体用例,但如果您需要对套接字做更多的工作,您可能想看看流行的python网络包。您还应该知道,许多GUI系统不喜欢从多个线程同时运行,因此您需要注意这一点。这与公认的答案基本相同,但对回调的强调程度较低。不管GUI是回调方法还是其他方法。问题是如何将对象传递给请求处理程序。该解决方案实际上是一个请求处理程序工厂,它接收GUI对象,并在创建该对象时将其传递给处理程序。有些人会建议通过服务器传递对象GUI,但这很尴尬,因为服务器与此无关。它甚至连看都不看。工厂也更灵活-您甚至可以使处理程序依赖于请求 工厂必须在处理程序的构造函数中传递对象GUI,因此此构造函数需要扩展我假设Python 3-使用super:
class SingleTCPHandler(SocketServer.BaseRequestHandler):
""" One instance per connection. """
def __init__(self, request, client_address, server, GUI):
# The GUI must be passed before we call the parent constructor
# because it actually handles the request and finishes it.
self._GUI = GUI
super().__init__(request, client_address, server)
def handle(self):
data = Net.recv_from_socket(self.request)
self._GUI.run(str("RECV'd message: %s" % data))
顺便说一句,目前,没有必要像中所讨论的那样将SocketServer.BaseRequestHandler子类化。我这样做,因为他们在文档中建议这样做,但是任何处理程序都可以使用——无需提供设置、处理和完成API。处理程序上没有约束,只是它必须处理请求。我们只需要定义工厂方法,当服务器调用该方法时,它将实例化处理程序并启动它,同时将GUI对象和连接请求传递给客户端:
class RequestHandlerFactory:
def __init__(self, GUI):
self._GUI = GUI
def start(self, request, client_address, server):
# The factory could even pass a different handler at each request!
# The application could change the handler while the server is running!
return SingleTCPHandler(self, request, client_address, server, self._GUI)
它们是这样使用的:
factory = RequestHandlerFactory(GUI)
with ServerUseFactory((HOST, PORT), factory.start) as server:
server.serve_forever()
这与公认的答案基本相同,但不太强调回调。不管GUI是回调方法还是其他方法。问题是如何将对象传递给请求处理程序。该解决方案实际上是一个请求处理程序工厂,它接收GUI对象,并在创建该对象时将其传递给处理程序。有些人会建议通过服务器传递对象GUI,但这很尴尬,因为服务器与此无关。它甚至连看都不看。工厂也更灵活——你甚至可以让处理器依赖于你 答应我的请求 工厂必须在处理程序的构造函数中传递对象GUI,因此此构造函数需要扩展我假设Python 3-使用super:
class SingleTCPHandler(SocketServer.BaseRequestHandler):
""" One instance per connection. """
def __init__(self, request, client_address, server, GUI):
# The GUI must be passed before we call the parent constructor
# because it actually handles the request and finishes it.
self._GUI = GUI
super().__init__(request, client_address, server)
def handle(self):
data = Net.recv_from_socket(self.request)
self._GUI.run(str("RECV'd message: %s" % data))
顺便说一句,目前,没有必要像中所讨论的那样将SocketServer.BaseRequestHandler子类化。我这样做,因为他们在文档中建议这样做,但是任何处理程序都可以使用——无需提供设置、处理和完成API。处理程序上没有约束,只是它必须处理请求。我们只需要定义工厂方法,当服务器调用该方法时,它将实例化处理程序并启动它,同时将GUI对象和连接请求传递给客户端:
class RequestHandlerFactory:
def __init__(self, GUI):
self._GUI = GUI
def start(self, request, client_address, server):
# The factory could even pass a different handler at each request!
# The application could change the handler while the server is running!
return SingleTCPHandler(self, request, client_address, server, self._GUI)
它们是这样使用的:
factory = RequestHandlerFactory(GUI)
with ServerUseFactory((HOST, PORT), factory.start) as server:
server.serve_forever()
这就是我的工作原理:
class MyServer():
def __init__(self, myGui, host='', port=8875):
myServer = socketserver.TCPServer((host, port), functools.partial(MyHandler, myGui))
myServer.serve_forever()
class MyHandler(socketserver.BaseRequestHandler):
def __init__(self, myGui, socket, client_address, tcpServer):
self.myGui = myGui
super().__init__(socket, client_address, tcpServer)
def handle(self):
...
这就是我的工作原理:
class MyServer():
def __init__(self, myGui, host='', port=8875):
myServer = socketserver.TCPServer((host, port), functools.partial(MyHandler, myGui))
myServer.serve_forever()
class MyHandler(socketserver.BaseRequestHandler):
def __init__(self, myGui, socket, client_address, tcpServer):
self.myGui = myGui
super().__init__(socket, client_address, tcpServer)
def handle(self):
...
啊,现在我明白了。这实际上回答了我的很多问题,谢谢!啊,现在我明白了。这实际上回答了我的很多问题,谢谢!检查这个,它似乎是相关的:检查这个,它似乎是相关的:什么是ServerUseFactory?什么是ServerUseFactory?