5

Я нашел this ограничитель скорости python decorator на основе redis классы. Как написать подобный декоратор, который использует только то, что доступно в стандартной библиотеке, которое можно использовать следующим образом?Ограничитель цен python decorator

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 на StackOverflow, но они не позволяют определить знаменатель.

ответ

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 приятно поймать! Я отредактировал код, не могли бы вы его проверить? –

Смежные вопросы