【问题标题】:How to implement Timeout in BaseHTTPServer.BaseHTTPRequestHandler Python如何在 BaseHTTPServer.BaseHTTPRequestHandler Python 中实现超时
【发布时间】:2010-12-11 23:45:04
【问题描述】:

在我的 python 脚本中,我正在尝试运行一个 Web 服务器:

server = BaseHTTPServer.HTTPServer(('127.0.0.1',8080), RequestHandler)

我有一个请求处理程序类:

class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    def do_GET(self):
        # Doing Some Stuff.

现在我总是在 do_GET 中等待一些数据。我想实现一个超时操作,我希望这个 Web 服务器在 60 秒后关闭。我无法实现这一点。请建议我在这种情况下如何实现 Web 服务器的自动关闭操作。

谢谢 塔拉辛格

【问题讨论】:

    标签: python basehttpserver


    【解决方案1】:

    假设我已正确理解您的问题,您无法在 do_GET 中实现读取超时,因为在调用此方法时请求已被读取。

    由于BaseHTTPRequestHandler 扩展了StreamRequestHandler,而BaseRequestHandler 又扩展了BaseRequestHandler,因此您可以覆盖setup() 以使用超时来初始化套接字:

    class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
      def setup(self):
        BaseHTTPServer.BaseHTTPRequestHandler.setup(self)
        self.request.settimeout(60)
    
      def do_GET(self):
        # ...
    

    【讨论】:

    • 我已经试过了,它不起作用。我是否需要与设置一起覆盖任何其他方法?我只想让服务器在 60 秒后自行关闭,无论正在处理什么。
    • 你应该在调用基类的setup()方法之前做self.timeout = 60(在内部它根据这个设置调用settimeout。)
    【解决方案2】:

    正如Tey'TinBane 的回答中指出的那样,timeout 属性不适用于serve_forever() 方法,如doc 中所述:

    解决方法是使用自定义循环来处理user3483992 指出的请求

    while True: server.handle_request()
    

    handle_request() 将按预期在给定超时结束时触发 handle_timeout() 方法:

    ...除了 handle_timeout 方法什么都不做:

    一个解决方案就是为此方法提供另一种实现,例如(信用here):

    server.handle_timeout = lambda: (_ for _ in ()).throw(TimeoutError())
    

    简而言之:

    try:
         server = HTTPServer(('', PORT_NUMBER), `yourAwesomeRequestHandler`)
         server.timeout = 10
         server.handle_timeout = lambda: (_ for _ in ()).throw(TimeoutError())
         while True: server.handle_request()
    except TimeoutError:
        // TODO
    

    【讨论】:

      【解决方案3】:

      我实际上发现,如果我随后调用超类,则在 def setup 中为 self.timeout 设置一个值不起作用。看起来处理程序的 setup 和 init 方法在创建 HTTPServer 实例期间没有被调用。我用 pydevd 确认了这一点。

      所以,我倒退了一步:

      httpd = BaseHTTPServer.HTTPServer(server_address, MyHttpHandler)
      httpd.timeout = 10
      

      完美运行,无需重写核心代码或构建您自己的派生类。如果您想这样做,您似乎必须覆盖 HTTPServer 代码,而不是 Handler 代码。

      【讨论】:

      • 有人可以确认这行得通吗?它看起来是迄今为止最简单的解决方案!
      • 我在生产代码(python 2.7.11)上使用它。如果它对我不起作用,那么我的代码将不起作用。我已经测试了不同的数字,很容易看到它在工作,因为当我删除它时,我的进程会挂起,直到它收到一个 http 请求,这可能是几个小时后。
      • 如果您之后调用serve_forever(大多数人可能会这样做),这不起作用。设置StreamRequestHandlertimeout 属性(正如其他人所建议的那样)总是有效的(但它不是documented)。
      • 适用于我的用例。我正在使用 httpd.handle_request()。尝试了各种方法,直到我找到了这个。谢谢!
      • 这很有趣,所以无论您使用的是serve_forever 还是handle_request,行为都会有所不同?我想知道这是不是有意的。
      【解决方案4】:
      class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
          timeout = 60 # StreamRequestHandler.setup
          def do_GET(self):
              # Doing Some Stuff.
      

      【讨论】:

      • 感谢您提供此代码 sn-p,它可能会提供一些有限的即时帮助。 proper explanation 将通过展示为什么这是解决问题的好方法,并使其对有其他类似问题的未来读者更有用,从而大大提高其长期价值。请edit您的回答添加一些解释,包括您所做的假设。
      【解决方案5】:

      我设法让 HTTP 请求超时

      self.rfile._sock.settimeout(60)
      

      希望对你有帮助

      【讨论】:

        【解决方案6】:
        timeout = 0.1  # seconds
        
        class WebHTTPServer(BaseHTTPServer.HTTPServer):
            def server_bind(self):
                BaseHTTPServer.HTTPServer.server_bind(self)
                self.socket.settimeout(timeout)
        
        class WebReqHandler(BaseHTTPServer.BaseHTTPRequestHandler):
            <etc> 
        
        if __name__ == '__main__':
            server = WebHTTPServer(('',port), WebReqHandler)
            while 1:
                server.handle_request()
                <do other things>
        

        【讨论】:

          【解决方案7】:
          class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
          def __init__(self, request, client_address, server):
              BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, request, client_address, server)   
              self.timeout = 60
          

          【讨论】:

          • self.timeout = 60需要在调用超类的构造函数之前设置,才能正常工作。
          猜你喜欢
          • 2011-07-12
          • 2011-10-26
          • 2011-04-11
          • 2017-03-25
          • 2011-03-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多