限速 python 装饰器
Rate-limiting python decorator
我发现 this 限速 python 装饰器基于 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)
Whosebug 上还有其他 answers 但它们不允许指定分母。
您可以使用 threading.Semaphore
to count and block the requests that are exceeding the limit, in combination with 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
我扩展了这个想法并在 PyPI 上发布了一个名为 limit 的库。
我发现 this 限速 python 装饰器基于 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)
Whosebug 上还有其他 answers 但它们不允许指定分母。
您可以使用 threading.Semaphore
to count and block the requests that are exceeding the limit, in combination with 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
我扩展了这个想法并在 PyPI 上发布了一个名为 limit 的库。