Quand j'appelle
self.client = ThreadedClient()
dans mon programme Python, j'obtiens l'erreur
"RuntimeError: le thread principal n'est pas dans la boucle principale"
J'ai déjà fait des recherches sur Google, mais je me suis trompé ... Quelqu'un peut-il m'aider, s'il vous plaît?
Erreur complète:
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
Des classes:
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
Vous exécutez votre boucle d'interface graphique principale dans un fil à part le fil principal. Tu ne peux pas faire ça.
Les docs mentionnent de manière désobligeante dans quelques endroits que Tkinter n'est pas tout à fait sûr, mais pour autant que je sache, ne dites jamais que vous ne pouvez parler à Tk que du fil principal. La raison en est que la vérité est un peu compliquée. Tkinter lui-même est thread-safe, mais il est difficile à utiliser de manière multithread. La documentation officielle la plus proche semble être cette page :
Q. Y at-il une alternative à Tkinter qui est thread-safe?
Tkinter?
Il suffit d'exécuter tout le code de l'interface utilisateur dans le fil principal et de laisser les rédacteurs écrire dans un objet de la file d'attente…
(L'exemple de code donné n'est pas génial, mais il suffit de comprendre ce qu'ils suggèrent et de faire les choses correctement.)
En fait, est une alternative thread-safe à Tkinter, mtTkinter . Et sa documentation explique assez bien la situation:
Bien que Tkinter soit techniquement sûr pour les threads (en supposant que Tk soit construit avec --enable-threads), il existe toujours des problèmes lorsqu'il est utilisé dans des applications Python multithreads. Les problèmes proviennent du fait que le module _tkinter tente de prendre le contrôle du thread principal via une technique d’interrogation lors du traitement des appels provenant d’autres threads.
Je pense que c'est exactement ce que vous voyez: votre code Tkinter dans Thread-1 tente de jeter un coup d'œil dans le thread principal pour trouver la boucle principale, et ce n'est pas là.
Alors, voici quelques options:
twisted
), elle peut avoir un moyen de s’intégrer à Tkinter, auquel cas vous devriez l’utiliser.mkTkinter
pour résoudre le problème.En outre, bien que je n’aie trouvé aucun doublon exact de cette question, il existe un certain nombre de questions connexes sur les SO. Voir cette question , cette réponse , et beaucoup d’autres pour plus d’informations.
Puisque tout ceci a aidé mon problème mais ne l'a pas résolu complètement, voici une chose supplémentaire à garder à l'esprit:
Dans mon cas, j'ai commencé à importer la bibliothèque pyplot dans de nombreux threads et à l'utiliser. Après avoir déplacé tous les appels de la bibliothèque vers mon thread principal, j'ai toujours cette erreur.
Je m'en suis débarrassé en supprimant toutes les instructions d'importation de cette bibliothèque dans d'autres fichiers utilisés dans d'autres threads. Même s'ils n'utilisaient pas la bibliothèque, la même erreur était causée par celle-ci.