2012-09-02 22 views
3

我正在實現一個使用ThreadingTCPServerBaseRequestHandler的自定義子類的python應用程序。這個問題是ThreadingTCPServer似乎自動產生線程並創建處理程序的實例,調用它們的handle()函數。然而,這使我無法將數據傳遞給處理程序,除了使用全局變量或類變量,這兩者似乎都是駭人聽聞的。有沒有更好的方法來做到這一點?使用python的SocketServer和兒童將額外的元數據傳遞給RequestHandler

理想的情況下,這應該是這樣的:

class ThreadedTCPServer(ThreadingTCPServer): 
    def process_request(self, *args, **kwargs): 
     ThreadingTCPServer.process_request(self, data, *args, **kwargs) 

與像

class ThreadedTCPRequestHandler(BaseRequestHandler): 
    def handle(self,data): 
     #do something with data 

回答

9

我偶然發現了同樣的事情。我的解決辦法如下:

class ThreadedTCPRequestHandler(SocketServer.StreamRequestHandler): 
    def handle(self): 
     print(self.server.mycustomdata) 

class ThreadedTCPServer(SocketServer.ThreadingTCPServer): 
    pass 

server = ThreadedTCPServer((args.host, args.port), ThreadedTCPRequestHandler) 
server.mycustomdata = 'foo.bar.z' 
server.serve_forever() 

的RequestHandler被稱爲與服務器對象作爲第三個參數,並將其保存爲self.server屬性,這樣你就可以訪問它。如果您將這個屬性設置爲一個可調用的,你可以很容易地調用它,也:

def handle(self): 
    mycustomdata = self.server.mycustomdata() 
+0

+1,今天再次遇到這個問題,這對我有用! –

1

處理程序由於handle由您BaseRequest子類實現,它可以從自身的數據,而不必它通過傳遞呼叫者,召集者。 (handle也可以是請求實例的一個可調用的屬性,如一個lambda顯式user_data arguments是地道的設計蟒通常不需要。)

綜觀SocketServer的代碼,它應該是直接的覆蓋finish_request傳遞額外的數據到您的BaseRequestHandler子類型的構造函數,它會將其存儲在handle的實例中以供使用。

1

第一個答案爲我工作,但我認爲這是清潔改變__init__方法,並傳遞屬性在構造函數中:

class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): 

    def __init__(self, host_port_tuple, streamhandler, Controllers): 
     super().__init__(host_port_tuple, streamhandler) 
     self.Controllers = Controllers 

注意第三個參數「控制器」在構造函數中,然後調用超沒有該參數,然後設置新的屬性控制器的財產self.Controllers。其餘的班級沒有變化。然後,在你Requesthandler,您可以訪問使用「服務器」屬性的參數,如上面所描述:

def handle(self):   
    self.Controllers = self.server.Controllers 
    <rest of your code> 

它更與上面相同的答案,但我覺得它乾淨了一點,因爲構造函數重載你只需在構造函數中添加你想要的屬性:

server = ServerInterface.ThreadedTCPServer((HOST, PORT), ServerInterface.ThreadedTCPRequestHandler, Controllers) 
相關問題