2014-10-05 41 views
0

经过大量研究,我不确定最佳实践是什么,我的下面的想法是否体面?如何限制Python 3中多线程程序中的API调用?

我想访问限制通话的总数,我可以做出50每分钟的API。

我的程序有多个线程独立运行。

如何限制我的程序保持在阈值以下?

我的想法是创建一个队列,并添加一两件事,它的每一个X秒,其中X = THREAD_COUNT/allowed_calls * 60。然后需要一个单独的线程来处理这些请求。 (并在固定时间间隔增加一个独立的线程)

将最好的做法是这样的事情是什么?有没有一种方法可以实现这一点,而不需要为每个小功能完全独立的线程?

+0

一般来说,管理队列需要API调用等等... – 2014-10-05 07:53:55

回答

2

你为什么不创建一个使用内部变量来控制呼叫的数量和关于第二个第一次调用类?

撕开这个代码 https://github.com/lucjon/Py-StackExchange/blob/master/stackexchange/web.py

基本上,它检查是否有比你需要和停止,如果是这样的话通话量多。 如果您正在使用多线程(如Pool),则传递函数请求作为要执行的函数。

class WebRequestManager(object): 
    # When we last made a request 
    window = datetime.datetime.now() 
    # Number of requests since last throttle window 
    num_requests = 0 

    def request(self, url, params): 
     now = datetime.datetime.now() 

     # Before we do the actual request, are we going to be throttled? 
     def halt(wait_time): 
      if self.throttle_stop: 
       raise TooManyRequestsError() 
      else: 
       # Wait the required time, plus a bit of extra padding time. 
       time.sleep(wait_time + 0.1) 

     if (now - WebRequestManager.window).seconds >= 1: 
      WebRequestManager.window = now 
      WebRequestManager.num_requests = 0 

     WebRequestManager.num_requests += 1 
     if WebRequestManager.num_requests > 30: 
      halt(5 - (WebRequestManager.window - now).seconds) 

     request = urllib.request.Request(url) 
     ... 
0

您可以使用限制其呼叫装饰:

import time, threading 

# make it work nice across threads 
def RateLimited(max_per_second): 
    ''' 
    Decorator that make functions not be called faster than 
    ''' 
    lock = threading.Lock() 
    minInterval = 1.0/float(max_per_second) 
    def decorate(func): 
    lastTimeCalled = [0.0] 
    def rateLimitedFunction(args,*kargs): 
     lock.acquire() 
     elapsed = time.clock() - lastTimeCalled[0] 
     leftToWait = minInterval - elapsed 

     if leftToWait>0: 
     time.sleep(leftToWait) 

     lock.release() 

     ret = func(args,*kargs) 
     lastTimeCalled[0] = time.clock() 
     return ret 
    return rateLimitedFunction 
    return decorate 

然后使用装饰:

@RateLimited(2) # 2 per second at most 
def PrintNumber(num): 
    print num 

if __name__ == "__main__": 
    print "This should print 1,2,3... at about 2 per second." 
    for i in range(1,100): 
    PrintNumber(i)