2014-02-07 52 views
14

Python文檔包括an example of creating an HTTP server如何將參數傳遞給RequestHandler?

def run(server_class=HTTPServer, handler_class=BaseHTTPRequestHandler): 
    server_address = ('', 8000) 
    httpd = server_class(server_address, handler_class) 
    httpd.serve_forever() 

RequestHandler類被提供給Server,然後採用自動實例化所述處理程序照顧。

比方說,我想在自定義參數傳遞到請求處理程序創建時。我該怎麼做,我該怎麼做?

更具體地說,我想從命令行傳入參數,並且必須在請求處理程序類中訪問sys.argv似乎不必要的笨重。

這似乎應該可以通過重寫部分Server類,但我覺得我忽略了一個更簡單和更好的解決方案。

+0

爲什麼不繼承處理程序類? – XORcist

+0

這似乎是socketserver庫設計中的一個主要缺陷 –

回答

12

使用類工廠:

def MakeHandlerClassFromArgv(init_args): 
    class CustomHandler(BaseHTTPRequestHandler): 
     def __init__(self, *args, **kwargs): 
      super(CustomHandler, self).__init__(*args, **kwargs) 
      do_stuff_with(self, init_args) 
    return CustomHandler 

if __name__ == "__main__": 
    server_address = ('', 8000) 
    HandlerClass = MakeHandlerClassFromArgv(sys.argv) 
    httpd = HTTPServer(server_address, HandlerClass) 
    httpd.serve_forever() 
+0

因此,在這種情況下,我不會將參數傳遞給構造函數,而是傳遞給其他位置? – Jakob

+0

@Jakob實際上,您不需要再傳遞參數,因爲它們在創建類時處於範圍之內。看我的編輯。 –

+0

不錯的解決方案。我認爲它應該是:self.do_stuff_with_self(init_args)。 – arhuaco

1

爲什麼不只是繼承了RequestHandler?

class RequestHandler(BaseHTTPRequestHandler): 
    a_variable = None 

class Server(HTTPServer): 
    def serve_forever(self, variable): 
     self.RequestHandlerClass.a_variable = variable 
     HTTPServer.serve_forever(self) 

def run(server_class=Server, handler_class=RequestHandler): 
    server_address = ('', 8000) 
    httpd = server_class(server_address, handler_class) 
    variable = sys.argv 
    httpd.serve_forever(variable) 
+0

我已經有一個'RequestHandler'子類。我可以將命令行參數傳遞給它,而不用硬編碼「sys.argv」嗎?這樣做會非常緊密地將該類與全局變量和腳本的命令行參數(例如,降低可測試性)聯繫起來。 – Jakob

+0

其實在這個例子中,我忽略了你使用'sys.argv'。我將仔細研究這種方法並嘗試一下。 – Jakob

+0

是的,你可以。也許你應該看看多處理庫。我過去所做的(不是命令行參數,但我猜你可以做類似的事情)是創建一個在RequestHandler進程和main之間共享的Queue(),然後RequestHandler等待一個QEvent。 – plover

5

我將在托馬斯·奧羅斯科的回答只是發表評論,但因爲我不能.. 或許這將幫助其他人誰也碰到了這個問題。在Python3之前,Python有「舊式」類,並且BaseHTTPRequestHandler似乎是其中之一。所以,工廠應該看起來像

def MakeHandlerClassFromArgv(init_args): 
    class CustomHandler(BaseHTTPRequestHandler, object): 
     def __init__(self, *args, **kwargs): 
      do_stuff_with(self, init_args) 
      super(CustomHandler, self).__init__(*args, **kwargs) 
    return CustomHandler 

爲了避免像TypeError: must be type, not classobj這樣的錯誤。

-2

可能像這樣訪問模塊級變量。

CONFIG = None 

class MyHandler(BaseHTTPRequestHandler): 
    def __init__(self, ... 
     self.config = CONFIG  # CONFIG is now 'stuff' 

if __name__ == "__main__": 
    global CONFIG 
    CONFIG = 'stuff' 
    server_address = ('', 8000) 
    httpd = HTTPServer(server_address, MyHandler) 
    httpd.serve_forever() 

參考Global Statement