wake-up-neo.com

RuntimeError: Der Haupt-Thread befindet sich nicht in der Hauptschleife

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
18
user2040823

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:

  • Machen Sie, was in den Tkinter-Dokumenten empfohlen wird, und verwenden Sie TkInter aus dem Haupt-Thread. Möglicherweise durch Verschieben Ihres aktuellen Hauptthreadcodes in einen Arbeitsthread.
  • Wenn Sie eine andere Bibliothek verwenden, die den Haupt-Thread übernehmen möchte (z. B. twisted), kann sie in Tkinter integriert werden. In diesem Fall sollten Sie diese verwenden.
  • Verwenden Sie 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.

25
abarnert

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.

1
Christian Mosz