简体   繁体   English

将参数传递给 SimpleHTTPRequestHandler

[英]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__方法:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM