【问题标题】:Tornado Async HTTP returning results incrementallyTornado 异步 HTTP 增量返回结果
【发布时间】:2012-08-10 11:22:16
【问题描述】:

根据我从 tornado.gen 模块文档中了解到的情况,tornado.gen.Task 由 tornado.gen.Callback 和 tornado.gen.Wait 组成,每个 Callback/Wait 对都与唯一键关联...

  @tornado.web.asynchronous
  @tornado.gen.engine
  def get(self):
      http_client = AsyncHTTPClient()
      http_client.fetch("http://google.com",
                        callback=(yield tornado.gen.Callback("google")))

      http_client.fetch("http://python.org",
                        callback=(yield tornado.gen.Callback("python")))

      http_client.fetch("http://tornadoweb.org",
                        callback=(yield tornado.gen.Callback("tornado")))
      response = yield [tornado.gen.Wait("google"), tornado.gen.Wait("tornado"), tornado.gen.Wait("python")]

      do_something_with_response(response)
      self.render("template.html")

所以上面的代码会得到来自不同 URL 的所有响应。 现在我真正需要完成的是在一个 http_client 返回数据后立即返回响应。因此,如果“tornadoweb.org”首先返回数据,它应该执行 self.write(respose) 并且 def get() 中的循环应该继续等待其他 http_clients 完成。 关于如何使用 tornado.gen 接口编写此内容的任何想法。

我正在尝试做的非常模糊的实现(并且在语法上不正确)会是这样的

class GenAsyncHandler2(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    @tornado.gen.engine
    def get(self):
        http_client = AsyncHTTPClient()
        http_client.fetch("http://google.com",
                          callback=(yield tornado.gen.Callback("google")))

        http_client.fetch("http://python.org",
                          callback=(yield tornado.gen.Callback("python")))

        http_client.fetch("http://tornadoweb.org",
                          callback=(yield tornado.gen.Callback("tornado")))

        while True:
            response = self.get_response()
            if response:
                self.write(response)
                self.flush()
            else:
                break
        self.finish()


    def get_response(self):
        for key in tornado.gen.availableKeys():
            if key.is_ready:
                value = tornado.gen.pop(key)
                return value
        return None

【问题讨论】:

    标签: python asynchronous tornado


    【解决方案1】:

    当你不应该使用inline callbacks时,即gen。 在所有回调完成后,还将调用self.render如果您想从服务器部分返回响应 - 部分呈现它。

    这样想(这是唯一有很大改进空间的想法):

      response = []
      @tornado.web.asynchronous
      def get(self):
          self.render('head.html')
          http_client = AsyncHTTPClient()
    
          http_client.fetch("http://google.com",
                            callback=self.mywrite)
    
          http_client.fetch("http://python.org",
                            callback=self.mywrite)
    
          http_client.fetch("http://tornadoweb.org",
                            callback=self.mywrite)
    
          self.render('footer.html')
          self.finish()
    
    
      def mywrite(self, result):
          self.render('body_part.html')
          self.response.add(result)
          if len(self.response) == 3:
            do_something_with_response(self.response)
    

    【讨论】:

      【解决方案2】:

      除此之外,实际上还有一个方法 WaitAll 等待所有结果,并在所有 HTTPCliens 完成响应后返回。 我已经在我的龙卷风分支 (https://github.com/pranjal5215/tornado) 中提交了差异。我添加了一个 WaitAny 类,它是异步 WaitAll 并在一个 HTTPClient 返回结果后立即返回结果。

      差异在 (https://github.com/pranjal5215/tornado/commit/dd6902147ab2c5cbf2b9c7ee9a35b4f89b40790e), (https://github.com/pranjal5215/tornado/wiki/Add-WaitAny-to-make-WaitAll-return-results-incrementally)

      示例用法:

      class GenAsyncHandler2(tornado.web.RequestHandler):
          @tornado.web.asynchronous
          @tornado.gen.engine
          def get(self):
              http_client = AsyncHTTPClient()
              http_client.fetch("http://google.com",
                                callback=(yield tornado.gen.Callback("google")))
      
              http_client.fetch("http://python.org",
                                callback=(yield tornado.gen.Callback("python")))
      
              http_client.fetch("http://tornadoweb.org",
                                callback=(yield tornado.gen.Callback("tornado")))
              keys = set(["google", "tornado", "python"])
              while keys:
                  key, response = yield tornado.gen.WaitAny(keys)
                  keys.remove(key)
                  # do something with response
                  self.write(str(key)+"        ")
                  self.flush()
              self.finish() 
      

      【讨论】:

        猜你喜欢
        • 2014-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-20
        • 2013-07-19
        • 1970-01-01
        相关资源
        最近更新 更多