2015-06-18 82 views
5

我發現this速率限制蟒蛇裝飾基於redis類。我該如何編寫一個類似的裝飾器,它只使用標準庫中可用的裝飾器,可以按如下方式使用它們?速率限制蟒蛇裝飾

def ratelimit(limit, every): 
    # python magic 

@ratelimit(limit=1, every=2) 
def printlimited(x): 
    print x 

# print one number every two seconds 
for x in range(10): 
    printlimited(x) 

上有計算器等answers但他們不允許指定分母。

回答

7

您可以使用threading.Semaphore來計數和阻止超出限制的請求,並結合threading.Timer來調度釋放信號量的函數。

from threading import Semaphore, Timer 
from functools import wraps 

def ratelimit(limit, every): 
    def limitdecorator(fn): 
     semaphore = Semaphore(limit) 
     @wraps(fn) 
     def wrapper(*args, **kwargs): 
      semaphore.acquire() 
      try: 
       return fn(*args, **kwargs) 
      finally:     # don't catch but ensure semaphore release 
       timer = Timer(every, semaphore.release) 
       timer.setDaemon(True) # allows the timer to be canceled on exit 
       timer.start() 
     return wrapper 
    return limitdecorator 
+0

如果包裝函數拋出異常,這將不會釋放信號量。你可以使用'try..finally'子句來確保發生。 –

+0

@PaulMFurley很好的接收!我編輯了代碼,你會檢查它嗎? –