threading tkinter add label in frame during function execution
Question: I write a pipeline for a lab, so I know it is impossible to insert a "console"
in a GUI, so I made it with a Frame and I put label on it.

But the problem is, I am a beginner in threading, and I don't know how to use
it to put my label into my frame after a function execution in a loop.

So this is my code (python 3.x) :

    
    
    ########
    # IMPORTS #
    ########
    
    from tkinter import *
    from tkinter import ttk
    from tkinter.filedialog import *
    from tkinter.messagebox import *
    import os
    import glob
    from datetime import date, time, datetime
    
    #########
    # FUNCTION #
    #########
    
    def OneFile(path1,DB,path2,seq,seq2,typ,path3):
        """
        This function is very long, take all the sequences of the input file and BLAST it to the Library DATABASE
        path : path to the library databse
        DB : library database name
        path2 : path of the file with the query sequences
        seq : name of the file with the query sequences append with a job ID
        seq2 : name of the file with the query sequence 
        Typ : Nucleotide or Proteine
        """
        from datetime import date, time, datetime
        import subprocess
        import platform
        import time
        OS = platform.system()
        if OS == 'Linux' or OS == 'Darwin':
            pathLibrary = path1+'/'
            pathSequence = path2+'/'
            pathFolder = path3+'/'
        if OS == 'Windows':
            pathLibrary = path1+'\\'
            pathSequence = path2+'\\'
        if typ not in [(1,1),(2,2),(1,2),(2,1)]:
            showerror('Error : Missing Type !', "You do not choose your type\n(nucleotides or proteins)")
        else:
            library = DB
            if os.path.isfile(pathLibrary+library) != True:
                showerror('Error : Missing File !', "You must choose a Library Database file")
            else:
                if os.path.isfile(pathSequence+seq2) != True:
                    showerror('Error : Missing File !', "You must choose your sequence file")
                else:
                    if typ == (1,1):
                        typ = "blastn"
                    if typ == (2,2):
                        typ = "blastp"
                    if typ == (1,2):
                        typ = "blastx"
                    if typ == (2,1):
                        typ = "tblastn"
                    if OS == 'Linux' or OS == 'Darwin':
                        t0 = time.time()
                        query = str(seq2)
                        blast = str(seq)+'_Blast.txt'
                        seqs = str(seq)+'_seqs.txt'
                        subprocess.call(typ+" -query "+pathSequence+query+" -db "+pathLibrary+library+" -evalue 1e-10 -out "+pathFolder+blast, shell=True)
                        subprocess.call("grep '\(Sbjct\|>\)' "+pathFolder+blast+" > "+pathFolder+seqs, shell=True)
                        t1 = time.time()
                        print('Job finish in '+str(round(t1-t0,2))+' seconds')
                    if OS == 'Windows':
                        t0 = time.time()
                        query = str(seq2)
                        blast = str(seq)+'_Blast.txt'
                        seqs = str(seq)+'_seqs.txt'
                        subprocess.call(typ+' -query '+pathSequence+query+' -db '+pathLibrary+library+' -evalue 1e-10 -out '+pathSequence+blast, shell=True)
                        print('Fichier n° '+str(1)+' '+str(seq2))
                        subprocess.Popen('findstr "Sbjct >" '+pathSequence+blast+' > '+pathSequence+seqs, shell=True)
                        t1 = time.time()
                        print('Job finish in '+str(round(t1-t0,2))+' seconds')
    
    #######
    # CLASS  #
    #######
    
    class GraphicalUserInterface():
        #principal application
        def __init__(self):
            #constructor
            self.fen = Tk()
            self.fen.title("Starch Enzyme Pipeline")
    
            #first label
            self.label1 = Label(self.fen, text="Folder with your set(s) : ")
            self.label1.grid(row=0, columnspan=2, sticky="W")
            #first button
            self.browse1 = Button(self.fen)
            self.browse1.config(text="Browse",command=self.folderPath)
            self.browse1.grid(row=1,column=0, sticky="W")
    
            #label to show the path
            self.varLabel1 = StringVar()
            self.pathLabel1 = Label(self.fen, textvariable=self.varLabel1, relief=SUNKEN)
            self.pathLabel1.grid(row=1,column=1, sticky="EW")
    
            #second title
            self.label2 = Label(self.fen, text="Folder with your library database(s) ")
            self.label2.grid(row=2,column = 0, columnspan=2 , sticky="W")
    
            #second button
            self.browse2 = Button(self.fen)
            self.browse2.config(text="Browse",command=self.folderPath2)
            self.browse2.grid(row=3,column=0, sticky="W")
    
            #label to show the path for database
            self.varLabel2 = StringVar()
            self.pathLabel2 = Label(self.fen, textvariable=self.varLabel2, relief=SUNKEN)
            self.pathLabel2.grid(row=3,column=1, sticky = "EW")
    
            #Frame wrappe listBox and other
            self.frameListBoxAll = Frame(self.fen)
            self.frameListBoxAll.grid(row=6,columnspan=2)
    
            #list box label
            self.labListBox1 = Label(self.frameListBoxAll, text="Your sets :",padx=10)
            self.labListBox1.grid(row=0,column=0)
            self.labListBox2 = Label(self.frameListBoxAll, text="Your library database :",padx=10)
            self.labListBox2.grid(row=0,column=1)
    
            #frame with listbox1
            self.frame1 = Frame(self.frameListBoxAll, bd=2, relief=SUNKEN)
            self.frame1.grid(row=1,column=0)
    
            #frame with listbox1
            self.frame2 = Frame(self.frameListBoxAll, bd=2, relief=SUNKEN)
            self.frame2.grid(row=1,column=1)
    
            #scrollbar listbox1
            self.scrollbar1 = Scrollbar(self.frame1)
            self.scrollbar1.grid(row=0,column=1, sticky="NS")
            self.scrollbar2 = Scrollbar(self.frame2)
            self.scrollbar2.grid(row=0,column=3, sticky="NS")
            self.scrollbar3 = Scrollbar(self.frame1, orient=HORIZONTAL)
            self.scrollbar3.grid(row=1,column=0, sticky="WE")
            self.scrollbar4 = Scrollbar(self.frame2, orient=HORIZONTAL)
            self.scrollbar4.grid(row=1,column=2, sticky="WE")
    
            #liste box
            self.listeBox1 = Listbox(self.frame1, selectmode=EXTENDED, exportselection=0, yscrollcommand=self.scrollbar1.set, xscrollcommand=self.scrollbar3.set)
            self.listeBox1.grid(row=0,column = 0)
            self.scrollbar1.config(command=self.listeBox1.yview)
            self.scrollbar3.config(command=self.listeBox1.xview)
    
            #liste box2
            self.listeBox2 = Listbox(self.frame2, selectmode=EXTENDED, exportselection=0, yscrollcommand=self.scrollbar2.set, xscrollcommand=self.scrollbar4.set)
            self.listeBox2.grid(row=0,column = 2)
            self.scrollbar2.config(command=self.listeBox2.yview)
            self.scrollbar4.config(command=self.listeBox2.xview)
    
            #radioboutton list box 1
            self.var = IntVar()
            for item in [1,2]:
                if item == 1:
                    self.rb = Radiobutton(self.frameListBoxAll, text='Nucleotides',value=item,variable=self.var)
                    self.rb.grid(row=2, column=0)
                if item == 2:
                    self.rb = Radiobutton(self.frameListBoxAll, text='Proteins',value=item,variable=self.var)
                    self.rb.grid(row=3, column=0)
    
            #radioboutton list box 2
            self.var2 = IntVar()
            for item in [1,2]:
                if item == 1:
                    self.rb2 = Radiobutton(self.frameListBoxAll, text='Nucleotides',value=item,variable=self.var2)
                    self.rb2.grid(row=2, column=1)
                if item == 2:
                    self.rb2 = Radiobutton(self.frameListBoxAll, text='Proteins',value=item,variable=self.var2)
                    self.rb2.grid(row=3, column=1)
            #variables
            self.path1 = str()
            self.path2 = str()
            self.path3 = str()
            #RUN Buttun
            self.runbutton = Button(self.fen, text="RUN",command=self.start_foo_thread).grid(row=7,column=0,columnspan=2)
    
            #FRAME CONSOLE
            self.console = Frame(self.fen)
            self.console.config(relief=SUNKEN, bg="black", height=200, width=400)
            self.console.grid(row=8, columnspan=10)
            self.console.grid_propagate(False) #to block the size of the frame
    
            #QUIT BUTTON
            self.quitButton = Button(self.fen)
            self.quitButton.config(text="QUIT", command=self.fen.destroy)
            self.quitButton.grid(row=100,column=0)
    
        def folderPath(self):
             path = askdirectory(title='Choose your set folder')
             self.varLabel1.set(path)
             self.listeBox1.delete(0, END)
             for filename in sorted(glob.glob(path+'/*')):
                 if os.path.isfile(filename):
                     #stockage of path
                     self.path1 = os.path.split(filename)[0]
                     name = os.path.split(filename)[1]
                     self.listeBox1.insert(END, name)
    
        def folderPath2(self):
            path = askdirectory(title="Choose your library database folder")
            self.varLabel2.set(path)
            self.listeBox2.delete(0, END)
            for filename in sorted(glob.glob(path+'/*')):
                if os.path.isfile(filename):
                    #stockage of path
                    self.path2 = os.path.split(filename)[0]
                    name = os.path.split(filename)[1]
                    self.listeBox2.insert(END, name)
    
        def run(self):
            self.fen.mainloop()
    
        def createJobName():
            job = str(datetime.now())
            job = job.replace(" ","-")
            return job
    
        def typeNP(self):
            liste = []
            #selection of query files
            valListBox1 = [self.listeBox1.get(idx) for idx in self.listeBox1.curselection()]
            #selection of database file
            valListBox2 = [self.listeBox2.get(idx) for idx in self.listeBox2.curselection()]
            #selection of sequence type
            typ = (self.var.get(),self.var2.get())
            # loop
            for i in range(len(valListBox2)):
                job = GraphicalUserInterface.createJobName()
                path1 = self.path2
                path2 = self.path1
                DB = valListBox2[i]
                path3 = os.getcwd()+"/"+DB+job
                if os.path.isdir(DB+job) == True:
                    showwarning('Warning', "The folder already exist \n or they are no folder name !\nChange or get the folder name")
                else:
                    os.mkdir(DB+job)
                for filename in valListBox1:
                    seq = filename+job
                    seq2 = filename
                    #stock data for OneFile function
                    liste.append([path1,DB,path2,seq,seq2,typ,path3])
            return liste
    
        def start_foo_thread(self):
            liste = self.typeNP()
            for i in range(len(liste)):
                global foo_thread
                import threading
                print('Fichier n°'+str(i+1)+' '+str(liste[i][4]))
                stringLabel = Label(self.console,text='Fichier n°'+str(i+1)+' '+str(liste[i][4]),bg='black', fg='white')
                stringLabel.grid(row=i,sticky="W")
                foo_thread = threading.Thread(target=OneFile(liste[i][0],liste[i][1],liste[i][2],liste[i][3],liste[i][4],liste[i][5],liste[i][6]))
                foo_thread.daemon = True
                foo_thread.start()
    
    
    
    #########
    # AUTORUN #
    #########
    
    if __name__ == '__main__':
        app = GraphicalUserInterface()
        app.run()
    

The problem is when the loop began in:

    
    
        def start_foo_thread(self):
            liste = self.typeNP()
            for i in range(len(liste)):
    

With the print function, I see the function run, but the label does not go in
the frame when the iteration finishes. When the loops are completed, I see my
label in the frame. What is the correct code to have my label in my frame at
the same time my function runs in my loop?


Answer: You sometimes have to manually update the widget. You have posted too much
code to wade through, so this simple example should show the problem. Run as
is, the labels don't show up until the function returns. Run with
update_idletasks() uncommented does what I think you want. Also note that the
program stops until the call to subprocess returns.

    
    
    import sys
    if sys.version_info[0] < 3:
        import Tkinter as tk     ## Python 2.x
    else:
        import tkinter as tk     ## Python 3.x
    
    class GraphicalUserInterface():
        def __init__(self):
            #constructor
            self.fen = tk.Tk()
            self.fen.title("Starch Enzyme Pipeline")
            self.console=tk.Frame(self.fen)
            self.console.grid()
            self.liste=["one", "two", "three"]
            tk.Button(self.fen, text="Exit", command=self.fen.quit).grid(row=1)
            self.start_foo_thread()
            self.fen.mainloop()
    
        def start_foo_thread(self):
            for ctr in range(len(self.liste)):
                lit='Fichier n %s' % (ctr)
                print(lit)
                stringLabel = tk.Label(self.console, text=lit,
                                       bg='black', fg='white')
                stringLabel.grid(row=ctr,sticky="W")
                ##self.console.update_idletasks()
            print("Waiting 2 seconds")
            self.fen.after(2000)  ## wait 2 seconds to show effect
            print("Return from function")
    
    if __name__ == '__main__':
        app = GraphicalUserInterface()
    

