0

我正在編寫這個程序,它使用線程同時下載多個文件並報告屏幕上每個文件的進度。 我正在使用一個不同的線程來下載每個文件。這是沒有問題的:Python Threading:多行進度報告

for file_url, filename in zip(file_urls, filenames): 
    th = Thread(target=download_file, args=(file_url, filename)) 
    threads.append(th) 
    th.start() 

for thread in threads: 
    thread.join() 

的問題是我不知道,反正我可以打印屏幕上的每個文件的進度報告,這將是這樣的:

"Downloading 'example1.zip': 54366 bytes of 2240799 70.7%" 
    "Downloading 'example2.zip': 31712 bytes of 1924639 64.7%" 
    "Downloading 'example3.zip': 21712 bytes of 3224979 34.7%" 

以下片段是單行進度報告:

def chunk_report(bytes_so_far, total_size, filename): 

    percent = float(bytes_so_far)/total_size 
    percent = round(percent * 100, 2) 
    print "Downloading '{0}': {1} of {2} {3:3.2g}% \r".format(filename, 
             bytes_so_far, total_size, percent), 

和輸出應該是這樣的:

"Downloading 'example2.zip': 31712 bytes of 1924639 64.7%" 

每次線程調用此函數時,它都會更新線程正在下載的文件的屏幕。

所以,問題是如何打印多行進度報告,就像我上面在python中說明的那樣?

在此先感謝。

回答

0

我會用隊列來報告進度報告線:

  1. 創建隊列
  2. 菌種每個下載線程傳遞隊列作爲參數
  3. 各有下載put進度信息,隊列
  4. 產生一個報告線程,從隊列中讀取進度消息並更新顯示器

模擬示例:

import threading 
import time 
import random 
import Queue 
import sys 

# a downloading thread 
def worker(path, total, q): 
    size = 0 
    while size < total: 
    dt = random.randint(1,3) 
    time.sleep(dt) 
    ds = random.randint(1,5) 
    size = size + ds 
    if size > total: size = total 
    q.put(("update", path, total, size)) 
    q.put(("done", path)) 

# the reporting thread 
def reporter(q, nworkers): 
    status = {} 
    while nworkers > 0: 
    msg = q.get() 
    if msg[0] == "update": 
     path, total, size = msg[1:] 
     status[path] = (total, size) 
     # update the screen here 
     show_progress(status) 
    elif msg[0] == "done": 
     nworkers = nworkers - 1 
    print "" 

def show_progress(status): 
    line = "" 
    for path in status: 
    (total, size) = status[path] 
    line = line + "%s: %3d/%d " % (path, size,total) 
    sys.stdout.write("\r"+line) 
    sys.stdout.flush() 

def main(): 
    q = Queue.Queue() 
    w1 = threading.Thread(target = worker, args = ("abc", 30, q)) 
    w2 = threading.Thread(target = worker, args = ("foobar", 25, q)) 
    w3 = threading.Thread(target = worker, args = ("bazquux", 16, q)) 
    r = threading.Thread(target = reporter, args = (q, 3)) 
    for t in [w1,w2,w3,r]: t.start() 
    for t in [w1,w2,w3,r]: t.join() 

main()