Python 受定时器影响的多处理

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:

我有一大堆要处理的事情。设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:
        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下载内容)。

Do
f
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!