我正在制作一些api请求,限制为每秒20次。至于得到答案,等待时间约为0.5秒我想使用multiprocessing.Pool.map并使用这个装饰器 rate-limiting 所以我的代码看起来像
def fun(vec):
#do stuff
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(20)
def multi(vec):
p = Pool(5)
return p.map(f, vec)
我有4个核心,这个程序运行正常,与循环版本相比,时间有所改善。此外,当Pool参数为4,5,6时它可以工作,Pool(6)的时间更短但是当我使用7+时我得到了错误(我想每秒连接多个连接)。
然后,如果我的函数更复杂并且可以执行1-5次请求,则装饰器不能按预期工作。 在这种情况下我还能用什么?
对于任何寻找使用池的人都要记得关闭它,否则你将使用所有的RAM
def multi(vec):
p = Pool(5)
res=p.map(f, vec)
p.close()
return res
我发现像WebRequestManager这样的东西可以解决问题。问题是多处理不起作用.Pool有19-20个进程,因为时间存储在运行请求时需要调用的类上。
答案 0 :(得分:0)
你的缩进在上面是不一致的,这使得回答这个问题变得更加困难,但是我会采取刺。
看起来你是限制错误的事情;如果f
应该被限制,则需要将呼叫限制为f
,而不是调用multi
。在发送到Pool
的内容中执行此操作将不起作用,因为分叉的工作人员将各自独立限制(分叉进程将独立跟踪自上次调用以来的时间)。
最简单的方法是限制Pool
拉出的迭代器产生结果的速度。例如:
import collections
import time
def rate_limited_iterator(iterable, limit_per_second):
# Initially, we can run immediately limit times
runats = collections.deque([time.time()] * limit_per_second)
for x in iterable:
runat, now = runats.popleft(), time.time()
if now < runat:
time.sleep(runat - now)
runats.append(time.time() + 1)
yield x
def multi(vec):
p = Pool(5)
return p.map(f, rate_limited_iterator(vec, 20))