Tornado异步HTTP以递增方式返回结果

pra*_*jal 5 python asynchronous tornado

据我所知,来自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")
Run Code Online (Sandbox Code Playgroud)

因此,上面的代码将获得来自不同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
Run Code Online (Sandbox Code Playgroud)

pra*_*jal 3

除此之外,实际上还有一个方法WaitAll,它会等待所有结果,并在所有HTTPClient 完成响应后返回。我已在我的龙卷风分支( 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-逐步

使用示例:

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() 
Run Code Online (Sandbox Code Playgroud)