Python 3 Multi-Threading with Tkinter
Question: I have been writing a bit of code that will eventually take commands from a
remote and local (within the code itself) source and and then will be carried
out and the results displayed using tkinter.

The Problem I am currently having is that when I run the code using threading
and queues this error appears and I have tried putting the gui code at the
bottom under the for loops for the threading but this had another error that
occurred.

    
    
    Exception in thread Thread-1:
    Traceback (most recent call last):
      File "C:\Python34\lib\threading.py", line 921, in _bootstrap_inner
        self.run()
      File "C:\Python34\lib\threading.py", line 869, in run
        self._target(*self._args, **self._kwargs)
      File "C:/Users/Eddy/Programing/Python/Sockets/GUI Server.py", line 60, in threader
        t_visuals()
      File "C:/Users/Eddy/Programing/Python/Sockets/GUI Server.py", line 49, in t_visuals
        label = Label(root, width=70, height=30,relief=RIDGE,bd=5,bg="white",textvariable=v,anchor=NW,justify= LEFT,font=("Times New Roman", 12)).grid(row=1,column=0)
      File "C:\Python34\lib\tkinter\__init__.py", line 2604, in __init__
        Widget.__init__(self, master, 'label', cnf, kw)
      File "C:\Python34\lib\tkinter\__init__.py", line 2122, in __init__
        (widgetName, self._w) + extra + self._options(cnf))
    RuntimeError: main thread is not in main loop
    
    Exception in thread Thread-2:
    Traceback (most recent call last):
      File "C:\Python34\lib\threading.py", line 921, in _bootstrap_inner
        self.run()
      File "C:\Python34\lib\threading.py", line 869, in run
        self._target(*self._args, **self._kwargs)
      File "C:/Users/Eddy/Programing/Python/Sockets/GUI Server.py", line 58, in threader
        t_connections()
      File "C:/Users/Eddy/Programing/Python/Sockets/GUI Server.py", line 43, in t_connections
        sLog_update("waiting for connection...")
      File "C:/Users/Eddy/Programing/Python/Sockets/GUI Server.py", line 40, in sLog_update
        v.set(g)
      File "C:\Python34\lib\tkinter\__init__.py", line 263, in set
        return self._tk.globalsetvar(self._name, value)
    RuntimeError: main thread is not in main loop
    

This is the code:

    
    
    from socket import *
    import time
    from tkinter import *
    import threading
    from queue import Queue
    
    #server setup
    HOST = ''
    PORT = 24601
    BUFSIZ = 1024
    ADDR = (HOST, PORT)
    
    tcpSerSock = socket(AF_INET, SOCK_STREAM)
    tcpSerSock.bind(ADDR)
    tcpSerSock.listen(5)
    
    #Window Setup
    HEIGHT = 720
    WIDTH = 1280
    root = Tk()
    root.title("Server Controler")
    root.geometry("1280x720")
    
    #Variables needed
    v =StringVar()
    f =StringVar()
    g = "" #Server update log
    
    #locked variables
    sLog_lock = threading.Lock()
    
    #t_ means threaded
    def sLog_update(self):
        with sLog_lock:
            global g
            currentTime = str("["+time.ctime()+"] ")
            g+=str(currentTime)
            g+=str(self)
            g+=str("\n")
            v.set(g)
    
    def t_connections():
        sLog_update("waiting for connection...")
        tcpCliSock, addr = tcpSerSock.accept()
        avr = "connected from: " + str(addr)
        sLog_update(avr)
    
    def t_visuals():
        label = Label(root, width=70, height=30,relief=RIDGE,bd=5,bg="white",textvariable=v,anchor=NW,justify= LEFT,font=("Times New Roman", 12)).grid(row=1,column=0)
        entry = Entry(root, width=105,relief=RIDGE,bd=5,textvariable=f).grid(row=2,column=0)
        button = Button(root,command= lambda:sLog_update(f.get()),text="send").grid(row=3,column=0)
        mainloop()
    
    def threader():
        worker = q.get()
        print(worker)
        if worker == 1:
            t_connections()
        elif worker == 0:
            t_visuals()
    
    q =Queue()
    
    for x in range(2):
        t = threading.Thread(target=threader)
        t.daemon = True
        t.start()
    
    for worker in range(20):
        q.put(worker)
    
    q.join()
    


Answer: You can make this problem going away by keeping all of the GUI code in the
main thread.

