Download progressbar for Python 3

前端 未结 2 1398
鱼传尺愫
鱼传尺愫 2020-12-05 20:26

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

相关标签:
2条回答
  • 2020-12-05 20:43

    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.

    0 讨论(0)
  • 2020-12-05 20:55

    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')
    
    0 讨论(0)
提交回复
热议问题