簡體   English   中英

在Python線程中,我如何跟蹤線程的完成?

[英]In Python threading, how I can I track a thread's completion?

我有一個python程序產生了許多線程。 這些線程持續2秒到30秒之間的任何時間。 在主線程中,我想跟蹤每個線程何時完成並打印消息。 如果我只是順序.join()所有線程和第一個線程持續30秒而其他線程更快完成,我將無法更快地打印消息 - 所有消息將在30秒后打印。

基本上我想阻塞,直到任何線程完成。 一旦線程完成,就打印一條關於它的消息,如果任何其他線程仍處於活動狀態,則返回阻塞狀態。 如果所有線程都已完成,則退出程序。

我能想到的一種方法是將隊列傳遞給所有線程並阻塞queue.get()。 每當從隊列接收到消息時,打印它,使用threading.active_count()檢查是否有其他線程處於活動狀態,如果是,則返回到queue.get()上的阻塞。 這可以工作,但是這里所有線程都需要遵循在終止之前向隊列發送消息的規則。

我想知道這是否是實現這種行為的傳統方式還是有其他/更好的方法?

需要使用Thread.is_alive()調用來檢查Thread.is_alive()

為什么不讓線程本身打印完成消息,或者在完成后調用其他完成回調?

您可以直接從主程序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!

這是@ 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"

我建議的是像這樣循環

while len(threadSet) > 0:
    time.sleep(1)
    for thread in theadSet:
        if not thread.isAlive()
            print "Thread "+thread.getName()+" terminated"
            threadSet.remove(thread)

休眠時間為1秒,因此線程終止和正在打印的消息之間會有輕微的延遲。 如果你能忍受這種延遲,那么我認為這是一個比你在問題中提出的更簡單的解決方案。

你可以讓線程將他們的結果推送到threading.Queue 讓另一個線程等待此隊列,並在出現新項目時立即打印該消息。

我不確定我看到使用的問題:threading.activeCount()

跟蹤仍處於活動狀態的線程數?

即使您不知道在啟動之前要啟動多少個線程,它似乎很容易跟蹤。 我通常通過列表理解生成線程集合,然后使用activeCount到列表大小的簡單比較可以告訴您已經完成了多少。

見這里: http//docs.python.org/library/threading.html

或者,一旦有了線程對象,就可以在線程對象中使用.isAlive方法來檢查。

我只是通過把它扔進一個多線程程序檢查我看起來很好:

for thread in threadlist:
        print(thread.isAlive())

當線程打開和關閉時,給我一個True / False列表。 所以你應該能夠這樣做並檢查任何錯誤,以便查看是否有任何線程完成。

我使用稍微不同的技術,因為我在我的應用程序中使用的線程的性質。 為了說明,這是我編寫的一個測試帶程序的片段,用於為我的線程類構建一個barrier類:

   while threads:
        finished = set(threads) - set(threading.enumerate())
        while finished:
            ttt = finished.pop()
            threads.remove(ttt)
        time.sleep(0.5)

我為什么這樣做? 在我的生產代碼中,我有一個時間限制,所以第一行實際上讀取“while threads和time.time()<cutoff_time”。 如果我到達截止點,那么我會有代碼告訴線程關閉。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM