如何使用装饰器对 Python 2.7 中的函数进行速率限制?
How can I rate limit a function in Python 2.7 with a decorator?
我正在尝试在 Python 中编写一个装饰器来限制函数在一段时间内被调用的次数。我预计会这样使用它:
@ratelimit(seconds=15)
def foo():
print 'hello'
start = time.time()
while time.time() - start < 10:
foo()
> 'hello'
> 'hello'
所以装饰函数最多可以在seconds
调用一次。在实施方面我有这个,但它不起作用,因为我不确定在后续调用之间保持 last_call
的正确方法:
import time
def ratelimit(seconds=10):
last_call = None # Never call decorated function
def decorator(func):
def wrapper(*args, **kwargs):
if last_call is None or time.time() - last_call > seconds:
result = func(*args, **kwargs)
last_call = time.time()
return result
return wraps(func)(wrapper)
return decorator
下面的代码在 python 2.7 中对我来说工作正常。
import time
from functools import wraps
last_called = dict() # When last called, and with what result
def ratelimit(seconds=10, timer=time.time):
def decorator(func):
last_called[func] = None
@wraps(func)
def wrapper(*args, **kwargs):
now = timer()
call_data = last_called.get(func, None)
if call_data is None or now - call_data[0] >= seconds:
result = func(*args, **kwargs)
last_called[func] = (now, result)
else:
result = call_data[1] # Replay rate-limited result
return result
return wrapper
return decorator
我正在尝试在 Python 中编写一个装饰器来限制函数在一段时间内被调用的次数。我预计会这样使用它:
@ratelimit(seconds=15)
def foo():
print 'hello'
start = time.time()
while time.time() - start < 10:
foo()
> 'hello'
> 'hello'
所以装饰函数最多可以在seconds
调用一次。在实施方面我有这个,但它不起作用,因为我不确定在后续调用之间保持 last_call
的正确方法:
import time
def ratelimit(seconds=10):
last_call = None # Never call decorated function
def decorator(func):
def wrapper(*args, **kwargs):
if last_call is None or time.time() - last_call > seconds:
result = func(*args, **kwargs)
last_call = time.time()
return result
return wraps(func)(wrapper)
return decorator
下面的代码在 python 2.7 中对我来说工作正常。
import time
from functools import wraps
last_called = dict() # When last called, and with what result
def ratelimit(seconds=10, timer=time.time):
def decorator(func):
last_called[func] = None
@wraps(func)
def wrapper(*args, **kwargs):
now = timer()
call_data = last_called.get(func, None)
if call_data is None or now - call_data[0] >= seconds:
result = func(*args, **kwargs)
last_called[func] = (now, result)
else:
result = call_data[1] # Replay rate-limited result
return result
return wrapper
return decorator