在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?