I tried making a GUI where there is a download button and it downloads a file from the internet. There is also a progressbar which shows progress of the download..
the whole code:
JavaScript
x
48
48
1
#minimal reproductive example..
2
3
import os
4
import time
5
import yaml
6
import urllib
7
import requests
8
import tempfile
9
import tkinter as tk
10
from tkinter import ttk
11
from tkinter import *
12
13
TEMP = tempfile.gettempdir()
14
15
def download(progressbar=None):
16
start = time.time()
17
url = 'https://proget.whirlpool.repl.co/information.yml'
18
local_filename = TEMP+"\"+url.split('/')[-1]
19
url_file = urllib.request.urlopen(url)
20
size= url_file.headers["Content-Length"]
21
print("Starting to download file", end = "r")
22
if progressbar:
23
progressbar['maximum'] = int(int(size)/1024)
24
with requests.get(url, stream=True) as r:
25
r.raise_for_status()
26
with open(local_filename, 'wb') as f:
27
sz = 0
28
for chunk in r.iter_content(chunk_size=8192):
29
f.write(chunk)
30
sz = sz+8192
31
if progressbar:
32
progressbar['value'] = progressbar['value'] + 8192
33
os.system(local_filename)
34
35
def Download(*args):
36
download(progressbar=pb95)
37
38
root = tk.Tk()
39
style = ttk.Style(root)
40
41
pb95 = ttk.Progressbar(root,orient='horizontal', mode='determinate',length=500, maximum=1)
42
pb95.pack(side='top',fill='y')
43
44
downloadbtn = tk.Button(root,text='Download',font='Consolas 30', bg='green', fg='white',relief='flat', command=Download)
45
downloadbtn.pack(side='bottom',fill='x')
46
47
root.mainloop()
48
but when i click on the download button, the whole window stops responding.. and after some time, when the download is finished, it responds.. and the progressbar becomes 100% done..
Advertisement
Answer
Try this:
JavaScript
1
69
69
1
import urllib
2
import requests
3
from tkinter import ttk
4
import tkinter as tk
5
6
# Import threading
7
from threading import Thread
8
9
10
def download(progressbar=None):
11
global progress_value, progress_maximum, progress_done
12
progress_value = 0
13
14
url = 'https://proget.whirlpool.repl.co/information.yml'
15
16
# I hard coded a large file for testing
17
url = "https://mirror.bytemark.co.uk/ubuntu-releases/21.04/ubuntu-21.04-desktop-amd64.iso"
18
# I also hard coded in a temp folder for testing
19
local_filename = "tmp/"+url.split('/')[-1]
20
url_file = urllib.request.urlopen(url)
21
size= url_file.headers["Content-Length"]
22
print("Starting to download file")
23
24
# If you want running the file to take 50% of the progressbar uncomment the `*2`
25
progress_maximum = int(size) # *2
26
27
file = open(local_filename, "wb")
28
with requests.get(url, stream=True) as r:
29
r.raise_for_status()
30
for chunk in r.iter_content(chunk_size=8192):
31
file.write(chunk)
32
progress_value += len(chunk)
33
file.close()
34
35
print("Running the file")
36
# os.system(local_filename)
37
print("Done")
38
progress_value = progress_maximum
39
progress_done = True
40
41
def Download(*args):
42
# Add a default value for the value of the progress bar:
43
global progress_value, progress_maximum, progress_done
44
progress_value = 0
45
progress_maximum = 1
46
progress_done = False
47
# Start the new thread
48
new_thread = Thread(target=download, daemon=True)
49
new_thread.start()
50
# Start the tkinter loop:
51
root.after(100, tkinter_download_loop)
52
53
def tkinter_download_loop():
54
pb95["maximum"] = progress_maximum
55
pb95["value"] = progress_value
56
# After 100 ms call `tkinter_download_loop` again
57
if not progress_done:
58
root.after(100, tkinter_download_loop)
59
60
root = tk.Tk()
61
62
pb95 = ttk.Progressbar(root, orient="horizontal", length=500)
63
pb95.pack(side="top", fill="y")
64
65
downloadbtn = tk.Button(root, text="Download", command=Download)
66
downloadbtn.pack(side="bottom", fill="x")
67
68
root.mainloop()
69
First of all, your code had a few mistakes:
- You keep opening the file in
"wb"
mode, which overrides the last chunk that you downloaded. - You divide the size by 1024 for no reason.
- Also the file you are downloading is very small. There is no need to iterate over it’s contents. The code above assumes that you have a large file
Things I did:
- I added a
tkinter
loop that uses global variables to communicate with a new thread. - That thread downloads the file.
- I also changed the url to a large file (> 1GB) just to check that it’s working properly.
- I also changed it so it opens the file only once so we can save the full file