在Python线程中,我如何跟踪线程的完成?

0cd*_*0cd 8 python multithreading

我有一个python程序产生了许多线程.这些线程持续2秒到30秒之间的任何时间.在主线程中,我想跟踪每个线程何时完成并打印消息.如果我只是顺序.join()所有线程和第一个线程持续30秒而其他线程更快完成,我将无法更快地打印消息 - 所有消息将在30秒后打印.

基本上我想阻塞,直到任何线程完成.一旦线程完成,就打印一条关于它的消息,如果任何其他线程仍处于活动状态,则返回阻塞状态.如果所有线程都已完成,则退出程序.

我能想到的一种方法是将队列传递给所有线程并阻塞queue.get().每当从队列接收到消息时,打印它,使用threading.active_count()检查是否有其他线程处于活动状态,如果是,则返回到queue.get()上的阻塞.这可以工作,但是这里所有线程都需要遵循在终止之前向队列发送消息的规则.

我想知道这是否是实现这种行为的传统方式还是有其他/更好的方法?

let*_*bee 6

需要使用该Thread.is_alive()调用检查该线程.


Mat*_*ipp 6

这是@detly 答案的一个变体,它允许您从主线程指定消息,而不是从目标函数打印它们。这将创建一个包装函数,该函数调用您的目标,然后在终止之前打印一条消息。您可以修改它以在每个线程完成后执行任何类型的标准清理。

#!/usr/bin/python

import threading
import time

def target1():
    time.sleep(0.1)
    print "target1 running"
    time.sleep(4)

def target2():
    time.sleep(0.1)
    print "target2 running"
    time.sleep(2)

def launch_thread_with_message(target, message, args=[], kwargs={}):
    def target_with_msg(*args, **kwargs):
        target(*args, **kwargs)
        print message
    thread = threading.Thread(target=target_with_msg, args=args, kwargs=kwargs)
    thread.start()
    return thread

if __name__ == '__main__':
    thread1 = launch_thread_with_message(target1, "finished target1")
    thread2 = launch_thread_with_message(target2, "finished target2")

    print "main: launched all threads"

    thread1.join()
    thread2.join()

    print "main: finished all threads"
Run Code Online (Sandbox Code Playgroud)


det*_*tly 5

为什么不让线程本身打印完成消息,或者在完成时调用其他完成回调?

您可以join从主程序中仅使用这些线程,因此您将看到一堆完成消息,并且当它们全部完成时,您的程序将根据需要终止。

这是一个快速简单的演示:

#!/usr/bin/python

import threading
import time

def really_simple_callback(message):
    """
    This is a really simple callback. `sys.stdout` already has a lock built-in,
    so this is fine to do.
    """    
    print message

def threaded_target(sleeptime, callback):
    """
    Target for the threads: sleep and call back with completion message.
    """
    time.sleep(sleeptime)
    callback("%s completed!" % threading.current_thread())

if __name__ == '__main__':
    # Keep track of the threads we create
    threads = []

    # callback_when_done is effectively a function
    callback_when_done = really_simple_callback

    for idx in xrange(0, 10):
        threads.append(
            threading.Thread(
                target=threaded_target,
                name="Thread #%d" % idx,
                args=(10 - idx, callback_when_done)
            )
        )

    [t.start() for t in threads]
    [t.join() for t in threads]

    # Note that thread #0 runs for the longest, but we'll see its message first!
Run Code Online (Sandbox Code Playgroud)