Python - 使用超时加入多个线程

时间:2014-06-05 16:47:19

标签: python multiprocessing

我有多个Process线程正在运行,我想加入所有以及timeout参数。我知道如果不需要超时,我可以写:

for thread in threads:
    thread.join()

我想到的一个解决方案是使用将所有线程连接在一起并尝试加入该线程的主线程。但是,我在Python中收到以下错误:

AssertionError: can only join a child process

我的代码如下。

def join_all(threads):
    for thread in threads:
        thread.join()

if __name__ == '__main__':
    for thread in threads:
        thread.start()

    master = multiprocessing.Process(target=join_all, args=(threads,))
    master.start()
    master.join(timeout=60)

4 个答案:

答案 0 :(得分:3)

您可以重复遍历每个线程,执行非阻塞检查以查看线程是否已完成:

import time

def timed_join_all(threads, timeout):
    start = cur_time = time.time()
    while cur_time <= (start + timeout):
        for thread in threads:
            if not thread.is_alive():
                thread.join()
        time.sleep(1)
        cur_time = time.time()

if __name__ == '__main__':
    for thread in threads:
        thread.start()

    timed_join_all(threads, 60)

答案 1 :(得分:1)

这个答案最初基于dano的答案,但有很多变化。

join_all获取线程列表和超时(以秒为单位)并尝试加入所有线程。它通过对Thread.join进行非阻止调用来实现此目的(通过将超时设置为0,将join设置为never timeout,无is_alive()}。

一旦完成所有线程(通过检查每个线程上的RuntimeError),循环将过早退出。

如果某些线程在超时发生时仍在运行,则该函数会引发import time def join_all(threads, timeout): """ Args: threads: a list of thread objects to join timeout: the maximum time to wait for the threads to finish Raises: RuntimeError: is not all the threads have finished by the timeout """ start = cur_time = time.time() while cur_time <= (start + timeout): for thread in threads: if thread.is_alive(): thread.join(timeout=0) if all(not t.is_alive() for t in threads): break time.sleep(0.1) cur_time = time.time() else: still_running = [t for t in threads if t.is_alive()] num = len(still_running) names = [t.name for t in still_running] raise RuntimeError('Timeout on {0} threads: {1}'.format(num, names)) if __name__ == '__main__': for thread in threads: thread.start() join_all(threads, 60) ,其中包含有关剩余线程的信息。

myTimer.Elapsed += (sender, e) => {secondsElapsed++;};

在我的使用中,它是在一个测试套件里面,其中线程是ExcThread的简化版本,所以如果线程从未完成运行,那就无所谓了。

答案 2 :(得分:0)

以下代码join是每个进程,等待一段时间。如果proc返回足够快,则超时减少,然后加入下一个进程。如果发生超时,则会显示错误消息,并且整个系统将退出到调用方。

import multiprocessing, sys, time

# start three procs that run for differing lengths of time
procs = [
    multiprocessing.Process(
        target=time.sleep, args=[num], name='%d sec'%num,
        )
    for num in [1,2,5]
]
for p in procs:
    p.start()
    print p

timeleft = 3.0
print 'Join, timeout after {} seconds'.format(timeleft)
for p in procs:
    orig = time.time()
    print '{}: join, {:.3f} sec left...'.format(p, timeleft)
    p.join(timeleft)
    timeleft -= time.time() - orig
    if timeleft <= 0.:
        sys.exit('timed out!')

超时

的示例
We start three procs: one waits for 1 sec, another for 3 sec, the last for 5 seconds. Then we `join` them, timing out after 3 seconds -- the last proc will be *interrupted*.

<Process(1 sec, started)>
<Process(2 sec, started)>
<Process(5 sec, started)>
Join, timeout after 3.0 seconds
<Process(1 sec, started)>: join, 3.000 sec left...
<Process(2 sec, started)>: join, 1.982 sec left...
<Process(5 sec, started)>: join, 0.965 sec left...
timed out!

答案 3 :(得分:0)

我在这里写这篇文章,只是为了确保我不会忘记它。答案的原则与dano的原则相同。此外,代码片段还有点pythonic:

threads = []
timeout = ...

# create and start the threads
for work in ...:
    thread = threading.Thread(target=worker)
    thread.daemon = True # without this the thread might outlive its parent
    thread.start()
    threads.append(thread)

# Wait for workers to finish or for timeout
stop_time = time.time() + timeout
while any(t.isAlive for t in threads) and (time.time() < stop_time):
    time.sleep(0.1)