2014-02-07 9 views
14

Die Python Dokumentation enthält an example of creating an HTTP server:Wie kann ich Parameter an einen RequestHandler übergeben?

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

A RequestHandler Klasse die Server vorgesehen ist, die dann dafür sorgt, automatisch den Handler instanziieren.

Angenommen, ich möchte benutzerdefinierte Parameter an den Anforderungshandler übergeben, wenn es erstellt wird. Wie kann und soll ich das tun?

Genauer gesagt möchte ich Parameter von der Befehlszeile übergeben, und sys.argv innerhalb der Request-Handler-Klasse scheint unnötig klobig.

Es scheint, dass dies möglich sein sollte durch Überschreiben von Teilen der Server Klasse, aber ich fühle mich wie ich eine einfachere und bessere Lösung übersehen.

+0

Siehe Warum nicht die Handler-Klasse Unterklasse? – XORcist

+0

Dies scheint ein großer Fehler in der Socketserver Bibliothek Design –

Antwort

12

eine Klasse Fabrik Verwendung:

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

Also in diesem Fall werde ich die Argumente nicht in den Konstruktor, sondern irgendwo sonst übergeben? – Jakob

+0

@Jakob Sie müssen die Argumente nicht mehr übergeben, da sie sich beim Erstellen der Klasse im Bereich befinden. Siehe meine Bearbeitung. –

+0

Schöne Lösung. Ich denke, es sollte sein: self.do_stuff_with_self (init_args). – arhuaco

1

Warum nicht nur die Requestunterklasse?

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

Ich habe bereits eine 'RequestHandler'-Unterklasse. Kann ich Befehlszeilenargumente an sie übergeben, ohne 'sys.argv' darin zu codieren? Dadurch wird die Klasse sehr eng mit globalen Variablen und den Befehlszeilenargumenten des Skripts verknüpft (z. B. die Testbarkeit wird reduziert). – Jakob

+0

Tatsächlich habe ich in diesem Beispiel Ihre Verwendung von 'sys.argv' übersehen. Ich schaue mir diese Methode genauer an und probiere sie aus. – Jakob

+0

Ja, du kannst. Vielleicht sollten Sie in die Multiprocessing-Bibliothek schauen. Was ich in der Vergangenheit getan habe (nicht für Kommandozeilenargumente, aber ich denke, Sie könnten etwas Ähnliches machen), ist eine Queue() zu erstellen, die zwischen dem RequestHandler-Prozess und dem Hauptteil geteilt wird, und dann der RequestHandler auf ein QEvent wartet. – plover

5

Ich würde Kommentar nur auf Antwort Thomas Orozco, aber da kann ich nicht .. Vielleicht wird dies anderes helfen, die auch in dieses Problem. Vor Python3 hat Python "Old-Style" -Klassen und BaseHTTPRequestHandler scheint einer von ihnen zu sein. So sollte die Fabrik aussehen

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 

, um Fehler wie TypeError: must be type, not classobj zu vermeiden.

-2

Sie könnte Zugriff auf die Modulebene Variable wie folgt.

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() 

zum Global Statement

Verwandte Themen