首页 > 解决方案 > 虽然循环不会在 python 多处理中中断

问题描述

由于我没有收到任何反馈,但对于这个问题,我在这里重新概念化(并简化)问题。在这个简化的情况下,我想知道如何重新启动不会在多处理队列中中断的 while 循环。

我想使用该multiprocessing库在多个内核上运行一个函数。

p = multiprocessing.Pool(5)                     # Start a pool with 5 cores
analysis = p.map(function_to_call,'abcdefghij') # Call function_to_call on every core 
                                                # each time with a different letter from
                                                # string 'abcdefghij' and collect results
print(analysis)

def function_to_call(arg):
    result = []
    time = timeit.default_timer()               # timeit library needed
    time_even = int(str(time)[-1])              # get last number of time
########## below can't be changed ###########
    while True:
        if (time_even % 2) == 0:                # if last number is even, do stuff
            result.append('problem')
        else:                                   # else append arg to result
            result.append(str(arg))
            break 
########## above can't be changed ###########
    print(result) 
    return(result)                              # and return result

脚本编译时的结果总是不同的。就我而言,终端的输出是:

['b']
['c']
['g']
['h']
['i']
['e']  # <--- note that the process run in parallel and not serial

'a'结论是,当使用参数、'd''f'和调用函数调用时,它会卡在 while 循环中'j'(因为在这些情况下时间戳的最后一个数字显然是偶数)。但是,如果我and False在 while 循环中添加 if 语句以使其始终中断,则会将以下内容打印到终端,表明一切工作正常(编译 print(result)):

['a']
['b']
['d']
['c']
['g']
['h']
['f']
['j']
['i']
['e']
[['a'], ['b'], ['c'], ['d'], ['e'], ['f'], ['g'], ['h'], ['i'], ['j']]

在我正在处理的脚本中,function_to_call 在某些情况下可能不会返回输出。但是,多次重新运行该函数最终会输出一个结果(我想用时间戳来模仿)。因此,我想调整我的脚本,以便在 function_to_call 不返回输出时使用相同的参数调用它。

不幸的是,我要调用的函数需要几个小时才能结束。所以我不想在一些预设的时间值之后强迫它中断。我会感谢每一个评论和所有建议!

标签: pythonwhile-loopmultiprocessing

解决方案


以指数级增加的超时重新运行它:

from stopit import ThreadingTimeout
timeout = 3600 # should probably be set slightly above the expected runtime
while True:
    with ThreadingTimeout(timeout) as timeout_ctx:
        result = function_to_call()
    if timeout_ctx.state != timeout_ctx.TIMED_OUT:
        return result
    timeout *= 2

这样,您就可以确定您平均不会做超过两倍的工作。

注意:我在示例中使用了 stopit 库https://github.com/glenfant/stopit


推荐阅读