Python 受定时器影响的多处理
我有一大堆要处理的事情。设f()为在L上操作的函数。f()接受另一个变量,该变量每15分钟过期一次,需要续订。以下是一个串行示例:Python 受定时器影响的多处理,python,timer,multiprocessing,Python,Timer,Multiprocessing,我有一大堆要处理的事情。设f()为在L上操作的函数。f()接受另一个变量,该变量每15分钟过期一次,需要续订。以下是一个串行示例: def main(): L = openList() # START THE CLOCK clockStart = dt.datetime.now() clockExp = clockStart + dt.timedelta(seconds=900) a = getRenewed() for item in L:
def main():
L = openList()
# START THE CLOCK
clockStart = dt.datetime.now()
clockExp = clockStart + dt.timedelta(seconds=900)
a = getRenewed()
for item in L:
f(item, a) # operate on item given a
# CHECK TIME REMAINING
clockCur = dt.datetime.now()
clockRem = (clockExp - clockCur).total_seconds()
# RENEW a IF NEEDED
if clockRem < 5: # renew with 5 seconds left
clockStart = dt.datetime.now()
clockExp = clockStart + dt.timedelta(seconds=900)
a = getRenewed()
def main():
L=openList()
#启动时钟
clockStart=dt.datetime.now()
clockExp=clockStart+dt.timedelta(秒=900)
a=getrendered()
对于L中的项目:
f(项目,a)#对给定a的项目进行操作
#检查剩余时间
clockCur=dt.datetime.now()
clockRem=(clockExp-clockCur).total_seconds()
#如有需要,请续约
如果clockRem<5:#在还剩5秒时更新
clockStart=dt.datetime.now()
clockExp=clockStart+dt.timedelta(秒=900)
a=getrendered()
因为f()需要几秒钟(有时甚至更长),所以我想将代码并行化。如果有计时器,有什么提示吗?我设想共享clockExp和“a”,当一个进程满足clockRem<5时,它调用getrendered()并共享新的“a”和clockExp,然后重复。如果
getrendered
是幂等的(也就是说,您可以多次调用它而不会产生副作用),您只需将现有的计时器代码移动到工作进程,当他们发现自己的计时器已经用完时,让他们每个人都打一次电话。这只需要同步您传入的列表中的项目,而且多处理。Pool
可以很容易地处理这一点:
def setup_worker():
global clockExp, a
clockStart = dt.datetime.now()
clockExp = clockStart + dt.timedelta(seconds=900)
a = getRenewed()
def worker(item):
global clockExp, a
clockCur = dt.datetime.now()
clockRem = (clockExp - clockCur).total_seconds()
if clockRem < 5: # renew with 5 seconds left
clockStart = dt.datetime.now()
clockExp = clockStart + dt.timedelta(seconds=900)
a = getRenewed()
f(item, a)
def main(L):
pool = multiprocessing.Pool(initializer=setup_worker)
pool.map(worker, L)
worker仍然需要有一些计时代码,因为否则您将面临竞争条件,其中一个worker可能会消耗从主进程在单个批中发送到队列的两个
a
值。如果对f
的某些调用比其他调用慢得多(这很可能是因为它们涉及从web下载内容)。Dof
或getrendered
依赖于任何特定于进程的状态,还是仅依赖(或修改)外部状态?f下载网站,由L中的项指定。GetRendered用于获取身份验证令牌。感谢提示。事实证明,我可以有多个活动令牌,所以第一个解决方案是有效的!
def setup_worker2(queue):
global x
x = random.random()
global a_queue, a, clockExp
a_queue = queue
a = a_queue.get() # wait for the first `a` value
clockStart = dt.datetime.now()
clockExp = clockStart + dt.timedelta(seconds=900)
def worker2(item):
global a, clockExp
clockCur = dt.datetime.now()
clockRem = (clockExp - clockCur).total_seconds()
if clockRem < 60: # start checking for a new `a` value 60 seconds before its needed
try:
a = a_queue.get_nowait()
clockStart = dt.datetime.now()
clockExp = clockStart + dt.timedelta(seconds=900)
except queue.Empty:
pass
return f(item, a)
def main2(L):
queue = multiprocessing.Queue() # setup the queue for the a values
pool = multiprocessing.Pool(initializer=setup_worker2, initargs=(queue,))
result = pool.map_async(worker2, L) # send the items to the pool asynchronously
while True: # loop for sending a values through the queue
a = getRenewed() # get a new item
for _ in range(os.cpu_count()):
queue.put(a) # send one copy per worker process
try:
result.wait(900-5) # sleep for ~15 minutes, or until the result is ready
except multiprocessing.TimeoutError:
pass # if we got a timeout, keep looping!
else:
break # if not, we are done, so break out of the loop!