[英]Pass Parameter to SimpleHTTPRequestHandler
I have to pass a parameter to SimpleHTTPRequestHandler class, so I used class factory to create a custom handler as below.我必须将一个参数传递给 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
This is my httpserver using the custom handler这是我使用自定义处理程序的 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()
and I start the server with然后我启动服务器
http_server = PythonHtpServer(port = 8123, serve_path = '/application/main.qml')
The server starts, but I get this error服务器启动,但出现此错误
AttributeError: CustomHandler instance has no attribute '_application_path'
Basically, from the error, the server did start but I don't know why it is not creating the attributes ( or the init is not called ).基本上,从错误来看,服务器确实启动了,但我不知道为什么它没有创建属性(或者没有调用 init )。 Please tell me where I am going wrong.请告诉我哪里出错了。 Any help would be welcome.欢迎任何帮助。
IMHO the simplest way is to make _application_path
a static attribute of the class. It is declared only at class declaration time, and can be used transparently by instances of the class:恕我直言,最简单的方法是使_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):
...
That way every new instance of the custom handler class will have access to the application path as self._application_path
.这样,自定义处理程序 class 的每个新实例都可以访问作为self._application_path
的应用程序路径。
Conceptually, you've written something like this (in this eg, application_path
~= var
):从概念上讲,你已经写了这样的东西(在这个例子中, 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
So the class is written to save the variable var
when an instance of MyClass
is created .所以写入class是为了在创建MyClass
实例时保存变量var
。 However, by the time the function finishes, the variable is destroyed , and since the class only returns a class definition and not a class instance , an instance of MyClass
does not get created by the time the original variable var
is destroyed, and thus the variable var
never actually gets saved by MyClass
.然而,当 function 完成时,变量被销毁,并且由于 class 仅返回 class定义而不是 class实例, MyClass
的实例不会在原始变量var
被销毁时创建,因此变量var
实际上从未被MyClass
保存。
INSTEAD, you can add var
as an argument to the MyClass.__init__
function, and create a generator class to handle creation of MyClass
instances, like so:相反,您可以将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)
The issue here that BaseHttpRequestHandler (and thus its subclass, SimpleHttpRequestHandler) never makes it out of its __init__
method:这里的问题是 BaseHttpRequestHandler(以及它的子类 SimpleHttpRequestHandler)永远不会脱离它的__init__
方法:
BaseHttpHandler__init__
... HttpServer 调用 SimpleHttpRequestHandler 的构造函数,它渗透到父类的BaseHttpHandler__init__
...BaseHttpHandler.__init__
calls handle
, which is overridden in... BaseHttpHandler.__init__
调用handle
,它被覆盖...BaseHttpRequestHandler.handle
, which loops forever (given default options). BaseHttpRequestHandler.handle
,它永远循环(给定默认选项)。 Thus, if you want to pass info along to your handler, you have to do it before calling the super's __init__
.因此,如果您想将信息传递给您的处理程序,则必须在调用 super 的__init__
之前完成。 I'm probably several years too late to help you, but for future readers, you can just switch the order of your __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)
I'd probably also use functools.partial instead of wrapping the whole thing in a function:我可能还会使用 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)
It's probably not a great idea to call super().__init__
at the end of your init in general (since it might mess up initialization), but here it seems like Python is kind of forcing your hand.一般来说,在 init 的末尾调用super().__init__
可能不是一个好主意(因为它可能会搞砸初始化),但这里似乎 Python 有点强迫你的手。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.