为什么matplotlib要求仅在主线程中进行绘制? [英] Why matplotlib requires to plot only in the main thread?

查看:169
本文介绍了为什么matplotlib要求仅在主线程中进行绘制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试绘制发电机的输出.

I'm trying to plot live the output of a generator.

以下代码按预期工作(Ctrl-C终止执行):

The following code works as expected (Ctrl-C terminates execution):

import numpy as np
import pylab as p
from Queue import Queue
from threading import Thread
import time

def dataGenerator():
    while True:
        yield np.random.random()

def populate():
    f = dataGenerator()
    while True:
        x = f.next(); y = f.next()
        q.put([x,y])

q = Queue()

p.figure(); p.hold(True); p.show(block=False)

populatorThread = Thread(target=populate)
populatorThread.daemon = True
populatorThread.start()

while True:
    data = q.get()
    x = data[0]
    y = data[1]
    p.plot(x,y,'o')
    p.draw()
    q.task_done()

populatorThread.join()

但是,如果我改为将绘图放置在线程中,则会得到RuntimeError: main thread is not in main loop:

However, if instead I put the plotting in a thread, I get RuntimeError: main thread is not in main loop:

import numpy as np
import pylab as p
from Queue import Queue
from threading import Thread
import time

def dataGenerator():
    while True:
        yield np.random.random()

def plotter():
    while True:
        data = q.get()
        x = data[0]
        y = data[1]
        p.plot(x,y,'o')
        p.draw()
        print x,y
        q.task_done()

q = Queue()

p.figure(); p.hold(True); p.show(block=False)

plotThread = Thread(target=plotter)
plotThread.daemon = True
plotThread.start()

f = dataGenerator()
while True:
    x = f.next()
    y = f.next()
    q.put([x,y])

plotThread.join()

为什么matplotlib关心绘制哪个线程?

Why does matplotlib care which thread does the plotting?

我不是在问如何解决这个问题,而是为什么会首先发生这种情况.

I'm not asking how to solve this but rather why is this happening in the first place.

推荐答案

可能是您用于后端的GUI. GUI可能希望在主线程中找到自己,但不是在matplotlib调用get_current_fig_manager().canvas.draw()时出现.

It's probably the GUI that you're using for backend. The GUI likely expects to find itself in the main thread, but it isn't when matplotlib calls get_current_fig_manager().canvas.draw().

例如,当我这样做时,我得到以下回溯:

For example, when I do this, I get the following traceback:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 763, in run
    self.__target(*self.__args, **self.__kwargs)
  File "tmp.py", line 18, in plotter
    p.draw()
  File "/usr/lib/pymodules/python2.7/matplotlib/pyplot.py", line 555, in draw
    get_current_fig_manager().canvas.draw()
  File "/usr/lib/pymodules/python2.7/matplotlib/backends/backend_tkagg.py", line 349, in draw
    tkagg.blit(self._tkphoto, self.renderer._renderer, colormode=2)
  File "/usr/lib/pymodules/python2.7/matplotlib/backends/tkagg.py", line 13, in blit
    tk.call("PyAggImagePhoto", photoimage, id(aggimage), colormode, id(bbox_array))
RuntimeError: main thread is not in main loop

请注意tk.call(...)行.您获得的异常不是从matplotlib引发的,而是从TkInter引发的.

Note the tk.call(...) line. The exception you get is not raised from matplotlib, it's raised from TkInter.

这篇关于为什么matplotlib要求仅在主线程中进行绘制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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