I am trying to copy a file and generate progress in a progress bar while it happens. I had to split the copying down to separate threads because tkinter wouldn't spawn the gui otherwise. All works fine with one thread, but as soon as a start another, the GUI doesn't update, it's just blank. Here's the code that matters:
def move_bar():
global stop
text.set(f'Moving {to_move[last_sep + 1:]}...')
while stop:
if mque.empty():
continue
else:
a = mque.get()
prog.set(a)
pgs.update()
else:
stop = 1
#copy_bar()
def copy_bar():
text.set(f'Copying {to_move[last_sep + 1:]}...')
while stop:
if cque.empty():
continue
else:
a = cque.get()
prog.set(a)
pgs.update()
else:
root.destroy()
def copyfile(src, dst):
global stop
pyway = 1024 * 1024 # Found this number in the shutil module
length = size if size < pyway else pyway
p = 0
with threading.Lock(): # Will be in it's own thread, lock till done
with open(src, 'rb') as fsrc, open(dst, 'wb') as fdst:
with memoryview(bytearray(length)) as mv:
while True:
# r (int) contains the size of the chunck written
r = fsrc.readinto(mv)
if not r:
break
elif r < length:
with mv[:r] as smv:
fdst.write(smv)
else:
fdst.write(mv)
cque.put(p)
p += r
stop = 0
def movefile(src, dst):
global stop
pyway = 1024 * 1024 # Found this number in the shutil module
p = 0
with threading.Lock(): # Will be in it's own thread, lock till done
length = size if size < pyway else pyway
with open(src, 'rb') as fsrc, open(dst, 'wb') as fdst:
with memoryview(bytearray(length)) as mv:
while True:
# r (int) contains the size of the chunck written
r = fsrc.readinto(mv)
if not r:
break
elif r < length:
with mv[:r] as smv:
fdst.write(smv)
else:
fdst.write(mv)
mque.put(p)
p += r
stop = 0
os.remove(src)
#to_move = sys.argv[1] # file dragged onto script
to_move = 'D:\\00.mkv'
size = os.stat(to_move).st_size
last_sep = to_move.rfind('\\')
# Create the GUI
root = T.Tk()
text = T.StringVar()
prog = T.IntVar()
lbl = T.Label(root, textvariable=text, font=(None, 13))
lbl.grid()
pgs = t.Progressbar(root, orient='horizontal', length=150, mode='determinate',
maximum=size, variable=prog)
pgs.grid(row=1)
s = time.time()
root.after(250, move_bar)
drives_dict = get_drive_name(get_drive_letters())
height = get_pixel_height(to_move)
# If I ever change my encodes so that DVDs height is more or less than
# 480, I'll have to change the next line:
if height == 480:
path1 = drives_dict['Back-Ups'] + 'My Movies\\DVD Rips\\'
path2 = drives_dict['Movies'] + 'DVD Rips\\'
else:
path1 = drives_dict['Back-Ups'] + 'My Movies\\Blu-ray Rips\\'
path2 = drives_dict['Movies'] + 'Blu-ray Rips\\'
move_to = path1 + to_move[last_sep + 1:]
copy_to = path2 + to_move[last_sep + 1:]
# Multiple threads because tkinter doesn't want to generate when the main
# thread is tied up:
t1 = threading.Thread(target=movefile, args=(to_move, move_to))
t1.start()
#t2 = threading.Thread(target=copyfile, args=(move_to, copy_to))
#t2.start()
root.mainloop()
Anyone have an idea why two threads mess up tkinter? Have I done something wrong?