RuntimeError:主线程不在主循环中 [英] RuntimeError: main thread is not in main loop

查看:144
本文介绍了RuntimeError:主线程不在主循环中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我打电话

self.client = ThreadedClient() 

在我的Python程序中,出现错误

in my Python program, I get the error

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

"RuntimeError: main thread is not in main loop"

我已经进行了一些谷歌搜索,但是我以某种方式出错了……有人可以帮帮我吗?

I have already done some googling, but I am making an error somehow ... Can someone please help me out?

完整错误:

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

课程:

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

推荐答案

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

You're running your main GUI loop in a thread besides the main thread. You cannot do this.

文档在一些地方不经意地提到Tkinter并不是线程安全的,但是据我所知,从来没有完全出来并说只能从主线程与Tk交谈.原因是事实有点复杂. Tkinter本身 是线程安全的,但很难以多线程方式使用.与此文档最接近的官方文档是此页面:

The docs mention offhandedly in a few places that Tkinter is not quite thread safe, but as far as I know, never quite come out and say that you can only talk to Tk from the main thread. The reason is that the truth is somewhat complicated. Tkinter itself is thread-safe, but it's hard to use in a multithreaded way. The closest to official documentation on this seems to be this page:

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

Q. Is there an alternative to Tkinter that is thread safe?

Tkinter?

只需在主线程中运行所有UI代码,然后让编写者将其写入Queue对象中即可.

Just run all UI code in the main thread, and let the writers write to a Queue object…

(给出的示例代码虽然不好,但足以弄清楚他们的建议并正确执行操作.)

(The sample code given isn't great, but it's enough to figure out what they're suggesting and do things properly.)

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

There actually is a thread-safe alternative to Tkinter, mtTkinter. And its docs actually explain the situation pretty well:

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

Although Tkinter is technically thread-safe (assuming Tk is built with --enable-threads), practically speaking there are still problems when used in multithreaded Python applications. The problems stem from the fact that the _tkinter module attempts to gain control of the main thread via a polling technique when processing calls from other threads.

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

I believe this is exactly what you're seeing: your Tkinter code in Thread-1 is trying to peek into the main thread to find the main loop, and it's not there.

所以,这里有一些选择:

So, here are some options:

  • 执行Tkinter文档的建议,并从主线程使用TkInter.可能是通过将当前的主线程代码移到工作线程中.
  • 如果您要使用其他一些要接管主线程的库(例如twisted),则它可能有一种与Tkinter集成的方法,在这种情况下,您应该使用它.
  • 使用mkTkinter解决此问题.
  • Do what the Tkinter docs recommend and use TkInter from the main thread. Possibly by moving your current main thread code into a worker thread.
  • If you're using some other library that wants to take over the main thread (e.g., twisted), it may have a way to integrate with Tkinter, in which case you should use that.
  • Use mkTkinter to solve the problem.

此外,虽然我没有找到这个问题的任何重复项,但关于SO还是有许多相关问题.请参阅此问题

Also, while I didn't find any exact duplicates of this question, there are a number of related questions on SO. See this question, this answer, and many more for more information.

这篇关于RuntimeError:主线程不在主循环中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆