2017-02-16 4 views
0

Ich habe eine spezielle Datenbankklasseninstanz, die ich in einen HTTPServer-Handler übergeben möchte, damit ich sie zur Verwendung in meinen do_GET- und do_POST-Callback-Handlern zurückgeben kann. Ich versuchte Subclassing, um meine Datenbank-Klasse als zusätzliches Argument für den Handler hinzuzufügen ... Das bringt es jedoch nicht vollständig in meine HTTPServerRequestHandler-Klasse.Wie bekomme ich HTTPServer, um meine eigene Klasse mit do_GETs zurückzugeben?

Was ich auch versucht, das nicht funktioniert:

Auch wenn ich das Argument der HTTPServerRequestHandler Klasse hinzugefügt zu bekommen gelingt, das schafft nur einen Fehler, da die serve_forever noch die Klasse mit der ursprünglichen Rückruf wird 4 (Selbst + 3) Argumente, wobei mein 5. (Datenbank-) Argument weggelassen wird.

Zuvor würde ich die Datenbank-Klasse als eine globale Konstante instanziieren, aber das scheint eine schlechte Idee. Hier

ist, was ich arbeiten so weit:

Dieser Code erfolgreich meine Seite dient, aber ich habe keinen Zugriff auf alle Datenbankmethoden (einschließlich meiner Protokollhandler, der ein Teil der Datenbankinstanz ist) :

def run_server(state_database, port): 
    state_database.log.info('starting server.') 
    server_address = ('', port) 

    HandlerClass = MakeHandlerClassforDB(state_database) 

    httpserver = HTTPServer(server_address, HandlerClass) 
    state_database.log.info('Server loaded.') 
    httpserver.serve_forever() 


def MakeHandlerClassforDB(state_database): 
    class CustomHandler(HTTPServerRequestHandler, object): 
     def __init__(self, *args, **kwargs): 
      self.database = state_database 
      super(CustomHandler, self).__init__(*args, **kwargs) 
    return CustomHandler 


# HTTPRequestHandler class 
# noinspection PyPep8Naming 
class HTTPServerRequestHandler(BaseHTTPRequestHandler): 
    def __init__(self, request, client_address, server): 
     BaseHTTPRequestHandler.__init__(self, request, client_address, server) 
     # would like to be able to get database into here as a self.... 
    def do_GET(self): 
     ip = self.client_address[0].split(".") 
     if ip[0] in self.page.blocked_ip_highs: 
      # `self.database` does not resolve, so this does not work... 
      self.database.log.info(
       "Ignored request from %s" % self.client_address) 
      return 
      ... 

    def do_POST(self): 
     time_start = time.time() 
     # again, self.database does not exist in the callback 
     self.database.log.debug(
      "Headers_________\n%s\n______________\n" % self.headers) 

ich mag auch diese 2 sowohl auf Python 3 und Python arbeiten

+0

Sorry, vielleicht ist es dumm ... aber warum machst du es nicht einfach global oder benutze einen globalen Singleton um es zu halten, der '' 'run_server''' könnte es einfach an den" Singleton "weitergeben (werde bei Interesse weiterarbeiten) –

+0

Ich sagte "dumm" ... hacky ist es angemessener. Wenn man sich den Code anschaut, scheint der RequestHandler die Serverinstanz im '' __init__''' zu bekommen ... hast du versucht, die 'database' an die Serverinstanz zu kleben und sie von dort zu benutzen? –

+0

Ich meinte den "httpserver", nach dem "httpserver = HTTPServer (server_address, HandlerClass)" versuche "httpserver.database = state_database", dann im 'HTTPServerRequestHandler' wenn du Zugriff auf den' server' hast einfach 'self'. Serverdatenbank. (nur ein geschlossen im Dunkeln) –

Antwort

0

Dies scheint zu funktionieren (was, warum ich super().__init__(...) nicht verwenden ist.):

def run_server(state_database, port): 
    server_address = ('', port) 

    handlerclass = makehandlerclassfordb(state_database) 
    httpserver = HTTPServer(server_address, handlerclass) 

    httpserver.serve_forever() 


def makehandlerclassfordb(state_database): 
    class CustomHandler(HTTPServerRequestHandler, object): 
     def __init__(self, *args, **kwargs): 
      self.database = state_database 
      self.page = HTMLPage() 

      super(CustomHandler, self).__init__(*args, **kwargs) 
    return CustomHandler 


class HTTPServerRequestHandler(BaseHTTPRequestHandler): 

    def do_GET(self): 
     self.database.log.debug(
      "Get Header_________%s______________" % self.headers) 

     """both self.page and self.database DO resolve (although 
      PyCharm does not think they should :P)""" 

     ip = self.client_address[0].split(".") 
     if ip[0] in self.page.blocked_ip_highs: 
      self.database.log.info(
       "Ignored request from %s" % self.client_address) 
      return 

Ich könnte die Elemente wieder der Klasse HTTPServerRequestHandler __init__ hinzufügen, aber dies ändert nicht die Funktionalität, und ich sehe keinen Grund, nur um einen IDE-Fehler weggehen.

Verwandte Themen