RunTimeError, Tkinter и мультипоточность
Создаю чат-сервер на socket и threading + tkinter Использую TCP/IP, server <-> client
Как я понял ошибка из-за особеностей ткинтера, но всё решения что я нашел в сети были индивидуальними.
Сама ошибка:
Exception in thread SendThread:
Traceback (most recent call last):
File "C:\Users\*******\AppData\Local\Programs\Python\Python38-32\lib\threading.py", line 932, in _bootstrap_inner
self.run()
File "C:\Users\Davyd\AppData\Local\Programs\Python\Python38-32\lib\threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "D:\restico_project\Python\chat_app\client.py", line 21, in send
data = entry.get()
File "C:\Users\******\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 3038, in get
return self.tk.call(self._w, 'get')
RuntimeError: main thread is not in main loop
Код сервера:
import time
import socket
import tkinter as tk
import threading as th
root = tk.Tk()
root.config(bg='#ffcA70')
root.title('SERVER')
root.geometry('500x500+550+200')
root.resizable(False, False)
def get():
while True:
data = con.recv(1024).decode('utf-8')
if data != ' ':
label_text = display_text.get() + '\n'
text['text'] = label_text + data
def send():
data = entry.get()
if data != ' ':
send_data = time.strftime('[%x %X] :: ') + data
con.send((send_data).encode('utf-8'))
label_text = display_text.get()
text = label_text + '\n[ YOU ] ' + send_data
send_thread = th.Thread(target=send, name='SendThread', daemon=True)
get_thread = th.Thread(target=get, name='GetThread', daemon=True)
display_text = tk.StringVar()
text = tk.Label(root, width=35, height=16, bg='#ffe5b3', font="Arial 14",
justify='left', anchor='sw', textvariable=display_text)
text.pack(side='top', pady=10)
wrap = tk.LabelFrame(root, text='Enter text...', bg='#ffcA70')
entry = tk.Entry(wrap, width=48, bg='#f1eee9')
send_but = tk.Button(wrap, width=19, height=2, text='Send', bg='#e7a54f', command=send)
wrap.pack(side='top', padx=5, pady=1, ipadx=2)
entry.pack(side='left')
send_but.pack(side='left')
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostbyname(socket.gethostname()), 2020))
s.listen(1)
con, addr = s.accept()
send_thread.start()
get_thread.start()
send_thread.join()
get_thread.join()
root.mainloop()
Код клиента:
import time
import socket
import tkinter as tk
import threading as th
root = tk.Tk()
root.config(bg='#ffe5b3')
root.title('CLIENT')
root.geometry('500x500+550+200')
root.resizable(False, False)
def get():
while True:
data = s.recv(1024).decode('utf-8')
if data != ' ':
label_text = display_text.get() +'\n'
text['text'] = label_text + data
def send():
data = entry.get()
if data != ' ':
send_data = time.strftime('[%x %X] :: ') + data
s.send((send_data).encode('utf-8'))
label_text = display_text.get()
text = label_text + '\n[ YOU ] ' + send_data
send_thread = th.Thread(target=send, name='SendThread', daemon=True)
get_thread = th.Thread(target=get, name='GetThread', daemon=True)
display_text = tk.StringVar()
text = tk.Label(root, width=35, height=16, bg='#f1eee9', font="Arial 14",
justify='left', anchor='sw', textvariable=display_text)
text.pack(side='top', pady=10)
wrap = tk.LabelFrame(root, text='Enter text...', bg='#ffe5b3')
entry = tk.Entry(wrap, width=48, bg='#f1eee9')
send_but = tk.Button(wrap, width=19, height=2, text='Send', bg='#e7a54f' , command=send)
wrap.pack(side='top', padx=5, pady=1, ipadx=2)
entry.pack(side='left')
send_but.pack(side='left')
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.0.103', 2020))
send_thread.start()
get_thread.start()
send_thread.join()
get_thread.join()
root.mainloop()
Ответы (1 шт):
Автор решения: restico
→ Ссылка
@CrazyElf:
Не помню как в Питоне, но обычно нигде нельзя работать с GUI не из основного потока.
Варианты решения этой проблемы для tkinter можно посмотреть здесь