RuntimeError:主线程不在主循环中

use*_*823 24 python multithreading tkinter

我打电话的时候

self.client = ThreadedClient() 
Run Code Online (Sandbox Code Playgroud)

在我的Python程序中,我收到错误

"RuntimeError:主线程不在主循环中"

我已经做了一些谷歌搜索,但我在某种程度上犯了错误...有人可以帮助我吗?

完整错误:

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
Run Code Online (Sandbox Code Playgroud)

类别:

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
Run Code Online (Sandbox Code Playgroud)

aba*_*ert 33

您在主线程之外的线程中运行主GUI循环.你不能做这个.

文档在少数几个地方提到Tkinter不是很安全,但据我所知,从来没有完全说出你只能从主线程中与Tk交谈.原因是事实有点复杂.Tkinter本身线程安全的,但很难以多线程方式使用.最接近官方文档的似乎是这个页面:

问:Tkinter是否有线程安全的替代方案?

Tkinter的?

只需在主线程中运行所有UI代码,让编写器写入Queue对象......

(给出的示例代码不是很好,但它足以弄清楚他们建议的是什么并正确地做事.)

实际上一个线程安全的替代Tkinter,mtTkinter.它的文档实际上很好地解释了这种情况:

尽管Tkinter在技术上是线程安全的(假设Tk是使用--enable-threads构建的),但实际上在多线程Python应用程序中使用时仍然存在问题.问题源于_tkinter模块在处理来自其他线程的调用时尝试通过轮询技术获得对主线程的控制.

我相信这正是你所看到的:你在Thread-1中的Tkinter代码试图查看主线程以找到主循环,但它并不存在.

所以,这里有一些选择:

  • 执行Tkinter文档推荐并从主线程中使用TkInter.可能通过将当前主线程代码移动到工作线程中.
  • 如果你正在使用其他一些想要接管主线程的库(例如twisted),那么它可能有一种与Tkinter集成的方法,在这种情况下你应该使用它.
  • 使用mkTkinter来解决这个问题.

此外,虽然我没有发现这个问题的任何确切重复,但有关于SO的一些相关问题.有关详细信息,请参阅此问题,此答案以及更多内容.


CPS*_*ore 15

我知道这已经晚了,但是我将线程设置为守护进程,并且没有引发异常:

t = threading.Thread(target=your_func)
t.setDaemon(True)
t.start()
Run Code Online (Sandbox Code Playgroud)


小智 6

我找到了解决它的方法。它可能看起来像一个笑话,但你应该添加

plt.switch_backend('agg')
Run Code Online (Sandbox Code Playgroud)

  • 没有任何迹象表明作者使用了 pyplot。 (2认同)