Python进程中的意外超时行为取决于被调用函数的返回值



给定以下程序:

import multiprocessing
import time
from multiprocessing import Process
import numpy as np

def run_process_timeout_wrapper(function, args, timeout):
def aux(n, out_q):
res = function(*n)
out_q.put(res)  # to get result back from thread target
result_q = multiprocessing.Queue()
p = Process(target=aux, args=(args, result_q))
p.start()
x = result_q.get()
p.join(timeout=timeout)
p.terminate()
if p.is_alive():
p.terminate()
raise multiprocessing.TimeoutError("Timed out after waiting for {}s".format(timeout))
return x

def foo(x):
return [(np.random.rand(50000), 0.993) for _ in range(10)]

def bar(x):
return x
def foobar(x):
res = [(np.random.rand(50000), 0.993) for _ in range(10000)]
return res

if __name__ == '__main__':
t1 = time.time()
res = run_process_timeout_wrapper(foo, (110,), 40)
print(time.time() - t1)
t1 = time.time()
res1 = run_process_timeout_wrapper(bar, (110,), 40)
print(time.time() - t1)
t1 = time.time()
res2 = run_process_timeout_wrapper(foobar, (110,), 1)
print(time.time() - t1)

这个程序的输出对于第一个进程是40秒,对于第二个进程大约是0秒。我知道返回数组需要比0多一点的时间,但我对发生的事情感到困惑。由于foo和bar的计算时间可能不到40秒(超时(,我希望两者都能快速完成并返回。

更新

感谢您提供有关使用join重新排序x.get((的答案。然而,我发现了另一个意想不到的行为,添加了一个应该超时的任务。运行最后一部分(foobar函数(现在似乎是不终止的,尽管我希望into在1秒后终止并引发TimeoutError

来自文档:

加入使用队列的进程

请记住,将项目放入队列的进程将在终止之前等待,直到所有缓冲项目都由"进料器"螺纹连接到下面的管道。(子进程可以调用队列的Queue.cancel_join_thread方法来避免这种情况行为。(

这意味着,无论何时使用队列,都需要确保已放入队列的所有项目最终在加入进程之前删除。否则你不能确定已将项目放入队列的进程将终止。还要记住,非守护进程将被加入自动地


因此,快速解决方法将把result_q.get()放在p.join():之前

x = result_q.get()
p.join(timeout=timeout)

相关内容

  • 没有找到相关文章

最新更新