tkinter progressbar for multiprocessing

2024/10/9 4:23:39

I have a program that encrypts files and I used multiprocessing to make it faster, but I am having trouble with the tkinter progress bar.

I have implemented it but it completes immediately or lags in between. The progressbar just completes to 100% but the files are still encrypting and i recieve no error.

files contains list of files.

The whole code is here - https://codeshare.io/pq8YxE

Below is the way i have implemented it.

def progbar():global pb_lableglobal percentglobal pbarglobal percentlabelglobal pbar_framepb_lable = tk.Label(root, text='Progress', font = "Raleway 13 bold")pb_lable.grid(row=5, columnspan=2, sticky='w', padx=(35))pbar_frame = tk.Frame(root)pbar_frame.grid(row=6, columnspan=2)pbar = Progressbar(pbar_frame,orient='horizontal',length=500,mode='determinate')pbar.grid(row=7,column=0, pady=10, padx=20)percent = tk.StringVar()percentlabel = tk.Label(root, textvariable=percent, font='Raleway 15')percentlabel.grid(row=5,columnspan=2,pady=10, padx=120, sticky='w')def encryptfn(key, a):f = Fernet(key)return f.encrypt(a)def enc(key, process_pool, file):task = len(files)x = 0with open(file,'rb') as original_file:original = original_file.read()encrypted = process_pool.apply(encryptfn, args=(key, original,))with open (file,'wb') as encrypted_file:encrypted_file.write(encrypted)pbar['value']+=100/taskx = x+1percent.set(str(int((x/task)*100))+'%')root.update_idletasks()def encfile():password = bytes('asdasd', 'utf-8')salt = bytes('zxcasd','utf-8')global filesfiles = filistbox.get(0,'end')if len(files) == 0:fierrorbox()elif len(password) == 0:passerrorbox()else:file_enc_button['state']='disabled'browsefi['state']='disabled'kdf = PBKDF2HMAC(algorithm=hashes.SHA256(),length=32,salt=salt,iterations=100,backend=default_backend())key = base64.urlsafe_b64encode(kdf.derive(password))MAX_THREADS = 300pool_size = min(MAX_THREADS, cpu_count(), len(files))process_pool = Pool(pool_size)thread_pool = ThreadPool(min(MAX_THREADS, len(files)))worker = partial(enc, key, process_pool)thread_pool.map(worker, files)root.event_generate("<<encryption_done>>")file_enc_button['state']='active'browsefi['state']='active'def run_encfile():root.bind('<<encryption_done>>', encryption_done)Thread(target=encfile).start()def encryption_done(*args):fiencdone()if __name__ == '__main__':root = tk.Tk()browsefi = tk.Button(root, text='Browse', command=fibrowse, borderwidth=3)browsefi.grid(row=2,column=0,padx=5, pady=5)##  File list  ##filist_frame = tk.Frame(root)filist_frame.grid(row=3, columnspan=2)filistbox = tk.Listbox(filist_frame, width=40, height=10)filistbox.grid(row=3,columnspan=2, pady=10)## Button ##fibutton_frame = tk.Frame(root)fibutton_frame.grid(row=4, columnspan=2)file_enc_button = tk.Button(fibutton_frame, text='Encrypt', width=15, command=run_encfile, borderwidth=3)file_enc_button.grid(row=4,column=0,padx=10,pady=15)progbar()percent.set('0%')root.mainloop()
Answer

The problem appears with function enc where you keep on resetting variable x back to 0.

You need a global variable, for example tasks_completed, initialized to 0, that keeps track of the number of encryptions that have been completed and gets incremented within enc with the statement tasks_completed += 1. Technically this is equivalent to tasks_completed = tasks_completed + 1 and is not an atomic operation and it is theoretically possible that the thread could be interrupted after reading the value of tasks_completed and therefore two threads would be updating tasks_completed to the same value. So this update, to be completely safe, should be done under control of a multithreading.Lock to ensure only one thread at a time can be doing the updating.

Replace function enc with:

from threading import Lock
tasks_completed = 0def enc(key, process_pool, lock, file):global tasks_completedwith open(file,'rb') as original_file:original = original_file.read()encrypted = process_pool.apply(encryptfn, args=(key, original,))with open (file,'wb') as encrypted_file:encrypted_file.write(encrypted)encrypted = process_pool.apply(encryptfn, args=(key, file,))with lock:tasks_completed += 1percentage_completed = int((tasks_completed / len(files)) * 100)pbar['value'] = percentage_completedpercent.set(f'{percentage_completed}%')root.update_idletasks()

And create a multiprocessing.Lock instance and pass it to enc in function encfile by modifying the function as follows:

lock = Lock() # create lock# add additional lock argument to enc:worker = partial(enc, key, process_pool, lock)
https://en.xdnf.cn/q/118630.html

Related Q&A

How to add and subtract in python

So I am making a statcalc and everything is working except adding. When I select the option to add it just skips it and says select an option. I was wondering whats wrong with it?numberstoadd = input(…

Python: deferToThread XMLRPC Server - Twisted - Cherrypy?

This question is related to others I have asked on here, mainly regarding sorting huge sets of data in memory.Basically this is what I want / have:Twisted XMLRPC server running. This server keeps seve…

How do I make a linear gradient with Python Turtle?

Im currently trying to replicate this image: https://i.sstatic.net/fymWE.jpg Im trying to make that gradient in the background but I have zero clue how to do it and theres basically nothing on the inte…

Python - Converting an array to a list causes values to change

>>> import numpy as np >>> a=np.arange(0,2,0.2) >>> a array([ 0. , 0.2, 0.4, 0.6, 0.8, 1. , 1.2, 1.4, 1.6, 1.8]) >>> a=a.tolist() >>> a [0.0, 0.2, …

Understand Python Function [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable…

how to download linkedin (save as pdf option) using python

Image what i want to download.Image is of LinkedIn profile page of my friend i want to click on that save-as-pdf option for many users.can that be downloaded using python code? for different users? o…

My tkinter entry box is printing .!entry instead of what is entered

from tkinter import * def _name_():businessname=entry_bnprint(businessname) edit_bar=Tk() name=Label(edit_bar,text="Name:").grid(row=0) entry_bn=Entry(edit_bar) entry_bn.grid(row=0,column=1) …

How to get an average from a row then make a list out of it [duplicate]

This question already has answers here:Reading a CSV file, calculating averages and printing said averages(2 answers)Closed 6 years ago.If I have a csv data that gives two row values of:years grades 20…

Beautiful soup: Extract everything between two tags when these tags have different ids

Beautiful soup: Extract everything between two tags I have seen a question through the above link where we are getting the information between two tags. Whereas I need to get the information between th…

exceptions.RuntimeError - Object has no attribute errno [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.Want to improve this question? Add details and clarify the problem by editing this post.Closed 6 years ago.Improve…