Wenn ich anrufe
self.client = ThreadedClient()
in meinem Python-Programm bekomme ich den Fehler
"RuntimeError: Hauptthread befindet sich nicht in Hauptschleife"
Ich habe schon ein bisschen gegoogelt, aber ich mache irgendwie einen Fehler ... Kann mir bitte jemand helfen?
Voller Fehler:
Exception in thread Thread-1:
Traceback (most recent call last):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 530, in __bootstrap_inner
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 483, in run
File "/Users/Wim/Bird Swarm/bird_swarm.py", line 156, in workerGuiThread
self.root.after(200, self.workerGuiThread)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 501, in after
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1098, in _register
RuntimeError: main thread is not in main loop
Klassen:
class ThreadedClient(object):
def __init__(self):
self.queue = Queue.Queue( )
self.gui = GuiPart(self.queue, self.endApplication)
self.root = self.gui.getRoot()
self.running = True
self.GuiThread = threading.Thread(target=self.workerGuiThread)
self.GuiThread.start()
def workerGuiThread(self):
while self.running:
self.root.after(200, self.workerGuiThread)
self.gui.processIncoming( )
def endApplication(self):
self.running = False
def tc_TekenVogel(self,vogel):
self.queue.put(vogel)
class GuiPart(object):
def __init__(self, queue, endCommand):
self.queue = queue
self.root = Tkinter.Tk()
Tkinter.Canvas(self.root,width=g_groottescherm,height=g_groottescherm).pack()
Tkinter.Button(self.root, text="Move 1 tick", command=self.doSomething).pack()
self.vogelcords = {} #register of bird and their corresponding coordinates
def getRoot(self):
return self.root
def doSomething():
pass #button action
def processIncoming(self):
while self.queue.qsize( ):
try:
msg = self.queue.get(0)
try:
vogel = msg
l = vogel.geeflocatie()
if self.vogelcords.has_key(vogel):
cirkel = self.vogelcords[vogel]
self.gcanvas.coords(cirkel,l.geefx()-g_groottevogel,l.geefy()-g_groottevogel,l.geefx()+g_groottevogel,l.geefy()+g_groottevogel)
else:
cirkel = self.gcanvas.create_oval(l.geefx()-g_groottevogel,l.geefy()-g_groottevogel,l.geefx()+g_groottevogel,l.geefy()+g_groottevogel,fill='red',outline='black',width=1)
self.vogelcords[vogel] = cirkel
self.gcanvas.update()
except:
print('Failed, was van het type %' % type(msg))
except Queue.Empty:
pass
Sie führen Ihre Haupt-GUI-Schleife in einem Thread neben dem Haupt-Thread aus. Du kannst das nicht machen.
In den Dokumenten wird an einigen Stellen beiläufig erwähnt, dass Tkinter nicht ganz threadsicher ist, aber meines Wissens nie ganz herauskommt und sagt, dass Sie nur über den Haupt-Thread mit Tk sprechen können. Der Grund ist, dass die Wahrheit etwas kompliziert ist. Tkinter selbst ist thread-sicher, aber es ist schwierig, Multithreading zu verwenden. Die offizielle Dokumentation hierzu scheint am nächsten zu sein diese Seite :
F. Gibt es eine Alternative zu Tkinter, die threadsicher ist?
Tkinter?
Führen Sie einfach den gesamten UI-Code im Haupt-Thread aus und lassen Sie die Autoren in ein Queue-Objekt schreiben.
(Der angegebene Beispielcode ist nicht großartig, aber es reicht aus, um herauszufinden, was sie vorschlagen und die Dinge richtig zu machen.)
Es gibt tatsächlich eine thread-sichere Alternative zu Tkinter, mtTkinter . Und seine Dokumente erklären die Situation tatsächlich ziemlich gut:
Obwohl Tkinter technisch thread-sicher ist (vorausgesetzt, Tk besteht aus --enable-threads), gibt es praktisch immer noch Probleme, wenn es in Multithread-Anwendungen Python verwendet wird. Die Probleme ergeben sich aus der Tatsache, dass das _tkinter-Modul versucht, die Kontrolle über den Hauptthread über eine Abfragetechnik zu erlangen, wenn Aufrufe von anderen Threads verarbeitet werden.
Ich glaube, das ist genau das, was Sie sehen: Ihr Tkinter-Code in Thread-1 versucht, in den Haupt-Thread zu schauen, um die Hauptschleife zu finden, und sie ist nicht da.
Also, hier sind einige Optionen:
twisted
), kann sie in Tkinter integriert werden. In diesem Fall sollten Sie diese verwenden.mkTkinter
, um das Problem zu lösen.Auch wenn ich keine genauen Duplikate dieser Frage gefunden habe, gibt es eine Reihe von verwandten Fragen zu SO. Weitere Informationen finden Sie unter diese Frage , diese Antwort und vielen anderen.
Da dies alles meinem Problem geholfen hat, es aber nicht vollständig gelöst hat, ist eine weitere Sache zu beachten:
In meinem Fall habe ich angefangen, die Pyplot-Bibliothek in viele Threads zu importieren und dort zu verwenden. Nachdem ich alle Bibliotheksaufrufe in meinen Haupt-Thread verschoben hatte, bekam ich immer noch diesen Fehler.
Ich habe es entfernt, indem ich alle Importanweisungen dieser Bibliothek in anderen Dateien entfernt habe, die in anderen Threads verwendet werden. Selbst wenn die Bibliothek nicht verwendet wurde, wurde derselbe Fehler dadurch verursacht.