2008-09-09 38 views
47

Tôi đang viết một ứng dụng nhỏ để tải xuống các tệp qua http (ví dụ: được mô tả here).Làm cách nào để viết chỉ báo tiến trình tải xuống bằng Python?

Tôi cũng muốn bao gồm một chút chỉ số tải về tiến trình thể hiện tỷ lệ tiến trình download.

Dưới đây là những gì tôi đã đưa ra:

 
    sys.stdout.write(rem_file + "...")  
    urllib.urlretrieve(rem_file, loc_file, reporthook=dlProgress) 

    def dlProgress(count, blockSize, totalSize): 
     percent = int(count*blockSize*100/totalSize) 
     sys.stdout.write("%2d%%" % percent) 
     sys.stdout.write("\b\b\b") 
     sys.stdout.flush() 

Output: MyFileName ... 9%

Bất kỳ ý tưởng hoặc đề nghị để làm điều này khác?

Một điều đó là hơi khó chịu là con trỏ nhấp nháy trong nhà ga trên chữ số đầu tiên của phần trăm. Có cách nào để ngăn chặn điều này? Có cách nào để ẩn con trỏ không?

EDIT:

Dưới đây là một lựa chọn tốt hơn sử dụng một biến toàn cầu cho tên tập tin trong dlProgress và '\ r' mã:

 
    global rem_file # global variable to be used in dlProgress 

    urllib.urlretrieve(rem_file, loc_file, reporthook=dlProgress) 

    def dlProgress(count, blockSize, totalSize): 
     percent = int(count*blockSize*100/totalSize) 
     sys.stdout.write("\r" + rem_file + "...%d%%" % percent) 
     sys.stdout.flush() 

Output: MyFileName ... 9%

Và con trỏ hiển thị ở cuối dòng. Tốt hơn nhiều.

+0

'rem_file' toàn cầu làm cho tinh thần chỉ bên trong một hàm mà bạn liên kết nó với một đối tượng mới 'rem_file = ...' nếu không (nếu bạn chỉ đọc giá trị của nó) 'global rem_file' là không cần thiết. – jfs

+0

Bạn cũng có thể thực hiện a/r + flush() theo tiêu chuẩn. Tôi chỉ đoán đây là chạy trong cửa sổ dựa trên hành vi thiết bị đầu cuối bạn đề cập đến. – meawoppl

+0

http://stackoverflow.com/questions/15644964/python-progress-bar-and-downloads –

Trả lời

17

Có một sự tiến bộ văn bản thư viện thanh cho python tại http://pypi.python.org/pypi/progressbar/2.2 mà bạn có thể tìm thấy hữu ích:

This library provides a text mode progressbar. This is tipically used to display the progress of a long running operation, providing a visual clue that processing is underway.

The ProgressBar class manages the progress, and the format of the line is given by a number of widgets. A widget is an object that may display diferently depending on the state of the progress. There are three types of widget: - a string, which always shows itself; - a ProgressBarWidget, which may return a diferent value every time it's update method is called; and - a ProgressBarWidgetHFill, which is like ProgressBarWidget, except it expands to fill the remaining width of the line.

The progressbar module is very easy to use, yet very powerful. And automatically supports features like auto-resizing when available.

+0

Chỉ tìm thấy điều này và nó rất dễ sử dụng. Cảm ơn vì tiền hỗ trợ! – Twisty

+0

làm thế nào để có nhiều thanh tiến trình trong thiết bị đầu cuối nếu nhiều tải được intimated trong các chủ đề riêng biệt? –

4

Nếu bạn sử dụng các gói curses, bạn có quyền kiểm soát lớn hơn nhiều của giao diện điều khiển. Nó cũng có chi phí cao hơn về độ phức tạp của mã và có thể không cần thiết trừ khi bạn đang phát triển một ứng dụng dựa trên giao diện điều khiển lớn.

Đối với một giải pháp đơn giản, bạn luôn có thể đặt bánh xe quay ở phần cuối của các messge trạng thái (chuỗi ký tự |, \, -, / mà thực sự trông đẹp dưới con trỏ nhấp nháy

13

Bạn cũng có thể thử:.

sys.stdout.write("\r%2d%%" % percent) 
sys.stdout.flush() 

Sử dụng một trở về vận chuyển duy nhất ở đầu của chuỗi của bạn chứ không phải là vài backspaces. Con trỏ của bạn vẫn sẽ nhấp nháy, nhưng nó sẽ nhấp nháy sau khi ký hiệu phần trăm chứ không phải dưới chữ số đầu tiên, và với một ký tự điều khiển thay vì ba bạn có thể ít bị nhấp nháy.

0

Đối với các file nhỏ, bạn có thể cần phải có dòng này để tránh tỷ lệ điên:

sys.stdout .write ("\ r% 2d %%" % phần trăm)

sys.stdout.flush()

Cheers

1

tôi đã sử dụng mã này:

url = (<file location>) 
file_name = url.split('/')[-1] 
u = urllib2.urlopen(url) 
f = open(file_name, 'wb') 
meta = u.info() 
file_size = int(meta.getheaders("Content-Length")[0]) 
print "Downloading: %s Bytes: %s" % (file_name, file_size) 

file_size_dl = 0 
block_sz = 8192 
while True: 
    buffer = u.read(block_sz) 
    if not buffer: 
     break 

    file_size_dl += len(buffer) 
    f.write(buffer) 
    status = r"%10d [%3.2f%%]" % (file_size_dl, file_size_dl * 100./file_size) 
    status = status + chr(8)*(len(status)+1) 
    print status, 

f.close() 
0

muộn để đảng, như thường lệ. Dưới đây là một thực hiện hỗ trợ báo cáo tiến độ, giống như lõi urlretrieve:

import urllib2 

def urlretrieve(urllib2_request, filepath, reporthook=None, chunk_size=4096): 
    req = urllib2.urlopen(urllib2_request) 

    if reporthook: 
     # ensure progress method is callable 
     if hasattr(reporthook, '__call__'): 
      reporthook = None 

     try: 
      # get response length 
      total_size = req.info().getheaders('Content-Length')[0] 
     except KeyError: 
      reporthook = None 

    data = '' 
    num_blocks = 0 

    with open(filepath, 'w') as f: 
     while True: 
      data = req.read(chunk_size) 
      num_blocks += 1 
      if reporthook: 
       # report progress 
       reporthook(num_blocks, chunk_size, total_size) 
      if not data: 
       break 
      f.write(data) 

    # return downloaded length 
    return len(data) 
6

Đối với những gì nó có giá trị, đây là đoạn code tôi sử dụng để làm cho nó làm việc:

from urllib import urlretrieve 
from progressbar import ProgressBar, Percentage, Bar 

url = "http://......." 
fileName = "file" 
pbar = ProgressBar(widgets=[Percentage(), Bar()]) 
urlretrieve(url, fileName, reporthook=dlProgress) 

def dlProgress(count, blockSize, totalSize): 
    pbar.update(int(count * blockSize * 100/totalSize)) 
+1

Điều này chỉ mang lại cho tôi: pbar.update (int (count * blocksize * 100/totalSize)) NameError: tên toàn cầu 'blocksize' không được xác định –

+0

đó là lỗi đánh máy. Nó phải là tham số đầu vào. Tôi đã cập nhật câu trả lời để phản ánh điều đó. Cảm ơn! – tstone2077

1
def download_progress_hook(count, blockSize, totalSize): 
    """A hook to report the progress of a download. This is mostly intended for users with slow internet connections. Reports every 5% change in download progress. 
    """ 
    global last_percent_reported 
    percent = int(count * blockSize * 100/totalSize) 

    if last_percent_reported != percent: 
    if percent % 5 == 0: 
     sys.stdout.write("%s%%" % percent) 
     sys.stdout.flush() 
    else: 
     sys.stdout.write(".") 
     sys.stdout.flush() 

    last_percent_reported = percent 

urlretrieve(url, filename, reporthook=download_progress_hook) 
Các vấn đề liên quan