[英]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.