I have created a simple program to download from a private azure container and rename a series of .jpg files listed in a csv file. I'm still learning python so I am sure the code is a bit on the rough side! That said, the code works fine and the files download correctly. However, I would like to display a pop up progress bar showing the current progress. I have looked at a number of examples but I'm not sure how best to approach this. Could anyone offer some pointers on the best way? Thanks.
from tkinter import messagebox
import urllib.request
import csv
from datetime import datetime, timedelta
from azure.storage.blob import BlockBlobService
from azure.storage.blob.models import BlobPermissions
from azure.storage.blob.sharedaccesssignature import BlobSharedAccessSignature
account_name = '***'
account_key = '***'
top_level_container_name = '***'
blob_service = BlockBlobService(account_name, account_key)
blob_shared = BlobSharedAccessSignature(account_name, account_key)
root = Tk()
root.withdraw()
csvDir = filedialog.askopenfilename(initialdir="/", title="SELECT CSV FILE", filetypes=(("CSV files", "*.csv"), ("all files", "*.*")))
imageDir = filedialog.askdirectory()
with open(csvDir) as images:
images = csv.reader(images)
img_count = 1
for image in images:
sas = blob_shared.generate_blob(container_name=top_level_container_name, blob_name=image[0], permission=BlobPermissions.READ, start=datetime.now(), expiry=datetime.now() + timedelta(hours=1))
sas_url = 'https://' + account_name + '.blob.core.windows.net' + '/' + top_level_container_name + '/' + image[0] + '?' + sas
print(sas_url)
urllib.request.urlretrieve(sas_url, imageDir + "/{}.jpg".format(image[1]))
img_count += 1
messagebox.showinfo("Complete", "Print images have been downloaded")
root.mainloop()
The base code that this project uses as its baseline is Shichao's Blog Post, Progress/speed indicator for urlretrieve() in Python and my version of it is simply a tkinter wrapper is big props to Shichao for the amazing Blog Post.
If you merely wish to see the code without the breakdown, you simply see it and copy and paste the given example:
import time
import urllib.request
import tkinter as tk
import tkinter.ttk as ttk
class download_toplevel:
def __init__(self, master):
self.master = master
self.download_button = tk.Button(self.master, text="Download", command=self.download)
self.download_button.grid(row=0, column=0)
self.root = tk.Toplevel(self.master)
self.progress_bar = ttk.Progressbar(self.root, orient="horizontal",
length=200, mode="determinate")
self.progress_bar.grid(row=0, column=0)
self.progress_bar.grid_rowconfigure(0, weight=1)
self.progress_bar.grid_columnconfigure(0, weight=1)
self.progress_bar["maximum"] = 100
self.root.withdraw()
# See https://blog.shichao.io/2012/10/04/progress_speed_indicator_for_urlretrieve_in_python.html
def reporthook(self, count, block_size, total_size):
print(count, block_size, total_size)
if count == 0:
self.start_time = time.time()
return
duration = time.time() - self.start_time
progress_size = int(count * block_size)
speed = int(progress_size / (1024 * duration))
percent = min(int(count*block_size*100/total_size), 100)
print(percent)
self.progress_bar["value"] = percent
self.root.update()
def save(self, url, filename):
urllib.request.urlretrieve(url, filename, self.reporthook)
def download(self):
self.progress_bar["value"] = 0
self.root.deiconify()
self.save("https://files02.tchspt.com/storage2/temp/discord-0.0.9.deb", "discord-0.0.9.deb")
self.root.withdraw()
def main():
root = tk.Tk()
#root.withdraw()
downloader = download_toplevel(root)
root.mainloop()
if __name__ == '__main__':
main()
import time
import urllib.request
import tkinter as tk
import tkinter.ttk as ttk
The import of tkinter.ttk
is important as the Progress Bar widget is not found in the default tkinter module.
def main():
root = tk.Tk()
downloader = download_toplevel(root)
root.mainloop()
if __name__ == '__main__':
main()
The line if __name__ == '__main__'
means if the code is run directly without being imported by another python program execute the following statement, so on you running $ python3 main.py
, the code will run the main
function.
The main function works by creating the main window root
, and passing the window into a variable within the class download_toplevel
. This is a neater way of writing python code and is more versatile when working with tkinter as it simplifies the code when looking at it in the future.
self.master = master
self.download_button = tk.Button(self.master, text="Download", command=self.download)
self.download_button.grid(row=0, column=0)
This code adds a button labelled download
bound to the command download
self.root = tk.Toplevel(self.master)
This creates a toplevel window that appears on top of the master
window
self.progress_bar = ttk.Progressbar(self.root, orient="horizontal",
length=200, mode="determinate")
self.progress_bar.grid(row=0, column=0)
self.progress_bar.grid_rowconfigure(0, weight=1)
self.progress_bar.grid_columnconfigure(0, weight=1)
self.progress_bar["maximum"] = 100
This creates a ttk.Progressbar
onto the Toplevel window, oriented in the x plane, and is 200px long. The grid_*configure(0, weight=1)
means that the progress bar should grow to fit the given space, to make sure this happens you should also include , sticky='nsew'
in the grid command. self.progress_bar["maximum"] = 100
means that the max value is 100%.
self.root.withdraw()
This withdraws the Toplevel window until it is actually required, ie when the download button is pressed.
def reporthook(self, count, block_size, total_size):
print(count, block_size, total_size)
if count == 0:
self.start_time = time.time()
return
duration = time.time() - self.start_time
progress_size = int(count * block_size)
speed = int(progress_size / (1024 * duration))
percent = min(int(count*block_size*100/total_size), 100)
This code is taken directly from Shichao's Blog Post, and simply works out the percentage completed.
self.progress_bar["value"] = percent
self.root.update()
The Progress Bar is then set to the current percentage and the Toplevel is updated, otherwise it remains as a black window (tested on Linux).
def save(self, url, filename):
urllib.request.urlretrieve(url, filename, self.reporthook)
This bit of code has been straight up taken from the Blog Post and simply downloads the file and on each block being downloaded and written the progress is sent to the self.reporthook
function.
def download(self):
self.progress_bar["value"] = 0
self.root.deiconify()
self.save("https://files02.tchspt.com/storage2/temp/discord-0.0.9.deb", "discord-0.0.9.deb")
self.root.withdraw()
The download function resets the Progress Bar to 0%, and then the root window is raised (outside of the withdraw). Then the save function is run, you may wish to rewrite the self.save
call to read self.after(500, [the_function])
so that your main window is still updated as this program is run. Then the Toplevel window is withdrawn.
Hope this helps, James
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.