我有这样的代码:
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
对象,以便它可以在本地调用函数,而不是引用全局变量。
思考?蟒蛇新手......
答案 0 :(得分:7)
将处理程序更改为
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 。这背后的“神奇”被称为“封闭”。即您可以从内部函数createHandler中的外部函数handler_factory访问回调参数。谷歌的“关闭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系统不喜欢从多个线程同时运行,因此您需要注意这一点。
答案 1 :(得分:0)
这与接受的答案基本相同,但不太重视回调。 GUI是回调方法还是其他什么都没关系。问题是如何将对象传递给请求处理程序。解决方案确实是一个请求处理程序工厂,它接收GUI(对象)并在创建它时将其传递给处理程序。有人会建议通过服务器传递对象(GUI),但它很尴尬,因为服务器与它无关。它甚至没有看到它。工厂也更灵活 - 你甚至可以根据要求制作处理程序!
工厂必须在处理程序的构造函数中传递对象(GUI),因此需要扩展此构造函数(我假设Python 3 - 使用super()):
SELECT cast_and_crew ->> 'content_id' AS content_id
FROM content_table
WHERE cast_and_crew ->> 'Actor' -> 'personName' = 'C. R. Simha'
BTW,目前,没有必要像https://bugs.python.org/issue29947中讨论的那样继承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
,setup
和handle
API。除了必须处理请求之外,处理程序没有约束。我们只需要定义工厂方法,当服务器调用时,它将实例化处理程序(并启动它),同时将GUI对象和连接(finish
)传递给客户端:
request
以这种方式使用:
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)
答案 2 :(得分:0)
这对我有用:
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):
...