有一个urlretrieve()
函数,可以将URL下载到文件,并允许指定一个回调函数来报告进度:
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:
sys.stderr.write("\n")
else:
sys.stderr.write("read %d\n" % (readsofar,))
urlretrieve(url, 'downloaded_file.py', reporthook)
这是一个图形用户界面进度条:
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:
def guiloop():
nonlocal root, progressbar
root = Tk()
root.withdraw()
progressbar = ttk.Progressbar(root, length=400)
progressbar.grid()
root.after(500, root.deiconify)
ready.set()
root.mainloop()
Thread(target=guiloop).start()
ready.wait(1)
percent = blocknum * blocksize * 1e2 / totalsize
if quit_id is None:
root.title('%%%.0f %s' % (percent, filename,))
progressbar['value'] = percent
if percent >= 100:
quit_id = root.after(0, root.destroy)
return urlretrieve(url, filename, reporthook)
download(url, 'downloaded_file.py')
在 Python 3.3 中,urlretrieve()
的reporthook
接口发生了变化(参见问题 16409)。为了解决这个问题,您可以通过FancyURLopener
访问先前的接口:
from urllib.request import FancyURLopener
urlretrieve = FancyURLopener().retrieve
要在同一线程中更新进度条,您可以内联urlretrieve()
代码:
from tkinter import Tk, ttk
from urllib.request import urlopen
def download2(url, filename):
response = urlopen(url)
totalsize = int(response.headers['Content-Length'])
outputfile = open(filename, 'wb')
def download_chunk(readsofar=0, chunksize=1 << 13):
percent = readsofar * 1e2 / totalsize
root.title('%%%.0f %s' % (percent, filename,))
progressbar['value'] = percent
data = response.read(chunksize)
if not data:
outputfile.close()
root.destroy()
else:
outputfile.write(data)
root.after(0, download_chunk, readsofar + len(data), chunksize)
root = Tk()
root.withdraw()
progressbar = ttk.Progressbar(root, length=400)
progressbar.grid()
root.after(500, root.deiconify)
root.after(0, download_chunk)
root.mainloop()
download2(url, 'downloaded_file.py')