Я прочитал ответы здесь: Что такое хороший алгоритм ограничения скорости?
Ответ от Карлоса А. Ибарры прекрасно работает без асинхронных возможностей, но есть ли способ изменить его, чтобы он работал асинхронно?
import time
def RateLimited(maxPerSecond):
minInterval = 1.0 / float(maxPerSecond)
def decorate(func):
lastTimeCalled = [0.0]
def rateLimitedFunction(*args,**kargs):
elapsed = time.clock() - lastTimeCalled[0]
leftToWait = minInterval - elapsed
if leftToWait>0:
time.sleep(leftToWait)
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)
Изменение time.sleep(leftToWait)
на await asyncio.sleep(leftToWait)
и ожидание PrintNumber(i)
работает для первого экземпляра, но не после. Я действительно новичок в Python и изо всех сил стараюсь соблюдать ограничение скорости API.
Моя реализация:
def rate_limited(max_per_second):
min_interval = 1.0 / float(max_per_second)
def decorate(func):
last_time_called = [0.0]
async def rate_limited_function(*args, **kargs):
elapsed = time.clock() - last_time_called[0]
left_to_wait = min_interval - elapsed
if left_to_wait > 0:
await asyncio.sleep(left_to_wait)
ret = func(*args, **kargs)
last_time_called[0] = time.clock()
return ret
return rate_limited_function
return decorate
class Test:
def __init__(self, bot):
self.bot = bot
@commands.command(hidden=True, pass_context=True)
@checks.serverowner()
async def test1(self, ctx):
await self.print_number()
@rate_limited(0.1)
def print_number(self):
print("TEST")