2016-09-27 50 views
0

我试图以异步方式在请求之间添加延迟。 当我使用Tornado gen.sleep(x)时,我的函数(启动)没有得到执行。 如果我删除收益产生gen.sleep(1.0),函数被调用,但没有延迟添加。 如何在我for循环中的请求之间添加延迟?我需要控制每秒对外部API的请求。 如果我使用time.sleep所有请求完成后,响应延迟。 试图添加@ gen.engine装饰器来启动函数并且没有结果。龙卷风gen.sleep添加延迟

代码:

import collections 
import tornado.httpclient 


class BacklogClient(object): 
    MAX_CONCURRENT_REQUESTS = 20 

    def __init__(self, ioloop): 
     self.ioloop = ioloop 
     self.client = tornado.httpclient.AsyncHTTPClient(max_clients=self.MAX_CONCURRENT_REQUESTS) 
     self.client.configure(None, defaults=dict(connect_timeout=20, request_timeout=30)) 
     self.backlog = collections.deque() 
     self.concurrent_requests = 0 

    def __get_callback(self, function): 
     def wrapped(*args, **kwargs): 
      self.concurrent_requests -= 1 
      self.try_run_request() 
      return function(*args, **kwargs) 

     return wrapped 

    def try_run_request(self): 
     while self.backlog and self.concurrent_requests < self.MAX_CONCURRENT_REQUESTS: 
      request, callback = self.backlog.popleft() 
      self.client.fetch(request, callback=callback) 
      self.concurrent_requests += 1 

    def fetch(self, request, callback=None): 
     wrapped = self.__get_callback(callback) 

     self.backlog.append((request, wrapped)) 
     self.try_run_request() 


import time 
from tornado import ioloop, httpclient, gen 


class TornadoBacklog: 
    def __init__(self): 

     self.queue = 0 
     self.debug = 1 
     self.toProcess = [ 
      'http://google.com', 
      'http://yahoo.com', 
      'http://nytimes.com', 
      'http://msn.com', 
      'http://cnn.com', 
      'http://twitter.com', 
      'http://facebook.com', 
     ] 


    def handle_request(self, response): 

     print response.code 
     if not self.backlog.backlog and self.backlog.concurrent_requests == 0: 
      ioloop.IOLoop.instance().stop() 


    def launch(self): 
     self.ioloop = ioloop.IOLoop.current() 
     self.backlog = BacklogClient(self.ioloop) 

     for item in self.toProcess: 
      yield gen.sleep(1.0) 
      print item 
      self.backlog.fetch(
       httpclient.HTTPRequest(
        item, 
        method='GET', 
        headers=None, 
       ), 
       self.handle_request 
      ) 

     self.ioloop.start() 



def main(): 
    start_time = time.time() 

    scraper = TornadoBacklog() 
    scraper.launch() 

    elapsed_time = time.time() - start_time 
    print('Process took %f seconds processed %d items.' % (elapsed_time, len(scraper.toProcess))) 


if __name__ == "__main__": 
    main() 

参考:https://github.com/tornadoweb/tornado/issues/1400

回答

1

龙卷风协同程序有两个组成部分:

  1. 它们包含 “产量” 报表
  2. 他们都装饰有 “gen.coroutine”

使用你的“推出”功能的“协同程序”装饰:

@gen.coroutine 
def launch(self): 

运行从开始龙卷风协同程序来完成这样的:

tornado.ioloop.IOLoop.current().run_sync(launch) 

删除调用“ioloop.start”从你的“启动”功能:循环运行“启动”功能,反之亦然。

+0

嗨,杰西,非常感谢你,我也摆脱了我在handle_request中的停止功能,一切正常。有没有办法检测客户端是否有未决请求?现在我添加了一个额外的延迟self.ioloop.start()曾经是。 – spicyramen

+1

要在所有请求完成后立即停止循环,请遵循Tornado文档中的并发web spider示例,它正在解决您的确切问题:http://www.tornadoweb.org/en/latest/guide/queues.html –