0

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?

malonn
  • 59
  • 1
  • 7
  • Please read this https://stackoverflow.com/a/63416839/13629335 – Thingamabobs Sep 10 '20 at 04:08
  • 1
    Thanks for the link. I will try an event object to signal the second thread after the first has complete. I was using locks on the threads, but my issues persist with locks, so let's see what an event can do. – malonn Sep 10 '20 at 13:44

0 Answers0