簡體   English   中英

將參數傳遞給 SimpleHTTPRequestHandler

[英]Pass Parameter to SimpleHTTPRequestHandler

我必須將一個參數傳遞給 SimpleHTTPRequestHandler class,所以我使用 class 工廠創建一個自定義處理程序,如下所示。

def RequestHandlerClass(application_path):    

  class CustomHandler(SimpleHTTPRequestHandler):

    def __init__(self, request, client_address, server):

        SimpleHTTPRequestHandler.__init__(self, request, client_address, server)
        self._file_1_done = False 
        self._file_2_done = False 
        self._application_path = application_path

    def _reset_flags(self):

        self._file_1_done = False 
        self._file_2_done = False 

    def do_GET(self):

        if (self.path == '/file1.qml'):
            self._file_1_done = True  

        if (self.path == '/file2.qml'):
            self._file_2_done = True 

        filepath = self._application_path + '/' + self.path  # Error here

        try:
            f = open(filepath) 
            self.send_response(200)
            self.end_headers()
            self.wfile.write(f.read())
            f.close()
        except IOError as e :
            self.send_error(404,'File Not Found: %s' % self.path)    


        if (self._file_1_done and self._file_2_done):
            self._reset_flags()  
            self.server.app_download_complete_event.set()
  return CustomHandler 

這是我使用自定義處理程序的 httpserver

class PythonHtpServer(BaseHTTPServer.HTTPServer, threading.Thread):

  def __init__(self, port, serve_path):
    custom_request_handler_class = RequestHandlerClass(serve_path)
    BaseHTTPServer.HTTPServer.__init__(self, ('0.0.0.0', port), custom_request_handler_class)
    threading.Thread.__init__(self)
    self.app_download_complete_event = threading.Event()

  def run(self):
    self.serve_forever()

  def stop(self):
    self.shutdown()    

然后我啟動服務器

http_server = PythonHtpServer(port = 8123, serve_path = '/application/main.qml')

服務器啟動,但出現此錯誤

AttributeError: CustomHandler instance has no attribute '_application_path'

基本上,從錯誤來看,服務器確實啟動了,但我不知道為什么它沒有創建屬性(或者沒有調用 init )。 請告訴我哪里出錯了。 歡迎任何幫助。

恕我直言,最簡單的方法是使_application_path成為 class 的 static 屬性。它僅在 class 聲明時聲明,並且可以被 class 的實例透明使用:

def RequestHandlerClass(application_path):    

  class CustomHandler(SimpleHTTPRequestHandler):

    _application_path = application_path   # static attribute

    def __init__(self, request, client_address, server):

        SimpleHTTPRequestHandler.__init__(self, request, client_address, server)
        self._file_1_done = False 
        self._file_2_done = False 

    def _reset_flags(self):
        ...

這樣,自定義處理程序 class 的每個新實例都可以訪問作為self._application_path的應用程序路徑。

從概念上講,你已經寫了這樣的東西(在這個例子中, application_path ~= var ):

def createClass(var):
    class MyClass:
        def __init__(self):
            self.var = var
        def func(self):
            # use var in some way
            print (self.var)
    # Return class definition
    return MyClass

所以寫入class是為了在創建MyClass實例時保存變量var 然而,當 function 完成時,變量被銷毀,並且由於 class 僅返回 class定義而不是 class實例MyClass的實例不會在原始變量var被銷毀時創建,因此變量var實際上從未被MyClass保存。

相反,您可以將var作為參數添加到MyClass.__init__ function,並創建一個生成器 class 來處理MyClass實例的創建,如下所示:

class MyClass:
    def __init__(self, arg1, arg2, var):
        (self.arg1, self.arg2, self.var) = (arg1, arg2, var)
    # Insert other methods as usual

class MyClassGenerator:
    def __init__(self, var):
        self.var = var
    def make(self, arg1, arg2):
        return MyClass(arg1, arg2, var)

這里的問題是 BaseHttpRequestHandler(以及它的子類 SimpleHttpRequestHandler)永遠不會脫離它的__init__方法:

因此,如果您想將信息傳遞給您的處理程序,則必須在調用 super 的__init__之前完成。 我可能來不及幫助你好幾年了,但對於未來的讀者來說,你可以改變你的__init__的順序:

class CustomHandler(http.server.SimpleHTTPRequestHandler):

  def __init__(self, *args, **kwargs):
    self._file_1_done = False 
    self._file_2_done = False
    self._application_path = application_path
    super().__init__(*args, **kwargs)

我可能還會使用 functools.partial 而不是將整個東西包裝在 function 中:

class CustomHandler(http.server.SimpleHTTPRequestHandler):

  def __init__(self, application_path, *args, **kwargs):
    self._file_1_done = False 
    self._file_2_done = False
    self._application_path = application_path
    super().__init__(*args, **kwargs)

...

custom_request_handler_class = functools.partial(CustomHandler, serve_path)
BaseHTTPServer.HTTPServer(('0.0.0.0', port), custom_request_handler_class)

一般來說,在 init 的末尾調用super().__init__可能不是一個好主意(因為它可能會搞砸初始化),但這里似乎 Python 有點強迫你的手。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM