[英]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__
方法:
BaseHttpHandler__init__
...BaseHttpHandler.__init__
調用handle
,它被覆蓋...BaseHttpRequestHandler.handle
,它永遠循環(給定默認選項)。 因此,如果您想將信息傳遞給您的處理程序,則必須在調用 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.