Download progressbar for Python 3

2019-01-17 23:28发布

I need a progress to show during file download for Python 3. I have seen a few topics on Stackoverflow, but considering that I'm a noob at programming and nobody posted a complete example, just fractions of it, or the one that I can make work on Python 3, none are good for me...

additional info:

ok, so i have this:

from urllib.request import urlopen
import configparser
#checks for files which need to be downloaded
print('    Downloading...')
file = urlopen(file_url)
#progress bar here
output = open('downloaded_file.py','wb')
output.write(file.read())
output.close()
os.system('downloaded_file.py')

script is run through python command line

2条回答
一夜七次
2楼-- · 2019-01-17 23:48

I think this piece of code can help you. I'm not quite sure it's exactly what you want. At least it should give you something to work on.

import tkinter 
from tkinter import ttk
from urllib.request import urlopen


def download(event):
    file = urlopen('http://www.python.org/')
    output = open('downloaded_file.txt', 'wb')
    lines= file.readlines()
    i = len(lines)

    for line in lines:
        output.write(line)
        pbar.step(100/i)

    output.close()
    file.close()




root = tkinter.Tk()
root.title('Download bar')

pbar = ttk.Progressbar(root, length=300)
pbar.pack(padx=5, pady=5)

btn = tkinter.Button(root, text="Download")
# bind to left mouse button click
btn.bind("<Button-1>", download)
btn.pack(pady=10)

root.mainloop()

This works, I've tried it.

查看更多
Lonely孤独者°
3楼-- · 2019-01-17 23:52

There is urlretrieve() that downloads an url to a file and allows to specify a reporthook callback to report progess:

#!/usr/bin/env python3
import sys
from urllib.request import urlretrieve

def reporthook(blocknum, blocksize, totalsize):
    readsofar = blocknum * blocksize
    if totalsize > 0:
        percent = readsofar * 1e2 / totalsize
        s = "\r%5.1f%% %*d / %d" % (
            percent, len(str(totalsize)), readsofar, totalsize)
        sys.stderr.write(s)
        if readsofar >= totalsize: # near the end
            sys.stderr.write("\n")
    else: # total size is unknown
        sys.stderr.write("read %d\n" % (readsofar,))

urlretrieve(url, 'downloaded_file.py', reporthook)

Here's a GUI progress bar:

import sys
from threading import Event, Thread
from tkinter import Tk, ttk
from urllib.request import urlretrieve

def download(url, filename):
    root = progressbar = quit_id = None
    ready = Event()
    def reporthook(blocknum, blocksize, totalsize):
        nonlocal quit_id
        if blocknum == 0: # started downloading
            def guiloop():
                nonlocal root, progressbar
                root = Tk()
                root.withdraw() # hide
                progressbar = ttk.Progressbar(root, length=400)
                progressbar.grid()
                # show progress bar if the download takes more than .5 seconds
                root.after(500, root.deiconify)
                ready.set() # gui is ready
                root.mainloop()
            Thread(target=guiloop).start()
        ready.wait(1) # wait until gui is ready
        percent = blocknum * blocksize * 1e2 / totalsize # assume totalsize > 0
        if quit_id is None:
            root.title('%%%.0f %s' % (percent, filename,))
            progressbar['value'] = percent # report progress
            if percent >= 100:  # finishing download
                quit_id = root.after(0, root.destroy) # close GUI

    return urlretrieve(url, filename, reporthook)

download(url, 'downloaded_file.py')

On Python 3.3 urlretrieve() has different reporthook interface (see issue 16409). To workaround it, you could access the previous interface via FancyURLopener:

from urllib.request import FancyURLopener
urlretrieve = FancyURLopener().retrieve

To update the progress bar within the same thread, you could inline urlretrieve() code:

from tkinter import Tk, ttk
from urllib.request import urlopen

def download2(url, filename):
    response = urlopen(url)
    totalsize = int(response.headers['Content-Length']) # assume correct header
    outputfile = open(filename, 'wb')

    def download_chunk(readsofar=0, chunksize=1 << 13):
        # report progress
        percent = readsofar * 1e2 / totalsize # assume totalsize > 0
        root.title('%%%.0f %s' % (percent, filename,))
        progressbar['value'] = percent

        # download chunk
        data = response.read(chunksize)
        if not data: # finished downloading
            outputfile.close()
            root.destroy() # close GUI
        else:
            outputfile.write(data) # save to filename
            # schedule to download the next chunk
            root.after(0, download_chunk, readsofar + len(data), chunksize)

    # setup GUI to show progress
    root = Tk()
    root.withdraw() # hide
    progressbar = ttk.Progressbar(root, length=400)
    progressbar.grid()
    # show progress bar if the download takes more than .5 seconds
    root.after(500, root.deiconify)
    root.after(0, download_chunk)
    root.mainloop()

download2(url, 'downloaded_file.py')
查看更多
登录 后发表回答