Matplotlib:多线程同时绘图

31 投票
2 回答
41099 浏览
提问于 2025-04-16 09:46

我正在尝试并行绘图,以便更快地完成大批量的工作。为此,我为每个计划制作的图形启动一个线程。

我原本希望每个线程能完成它的绘图任务后自动关闭自己(根据我的理解,Python会在线程执行完所有的指令后自动关闭它)。下面的代码展示了这种行为。

如果注释掉创建图形的那一行,程序就能按预期运行。还有一个可能有帮助的信息是,当只启动一个线程时,它也能正常运行。

import matplotlib.pyplot as plt
import time
import Queue
import threading

def TapHistplots():
    ##  for item in ['str1']:
# # it behaves as expected if the line above is used instead of the one below
    for item in ['str1','str2']:
        otheritem = 1
        TapHistQueue.put((item, otheritem))
        makeTapHist().start()

class makeTapHist(threading.Thread):
    def run(self):
        item, otheritem = TapHistQueue.get()
        fig = FigureQueue.get()
        FigureQueue.put(fig+1)
        print item+':'+str(fig)+'\n',
        time.sleep(1.3)
        plt.figure(fig) # comment out this line and it behaves as expected
        plt.close(fig)

TapHistQueue = Queue.Queue(0)
FigureQueue = Queue.Queue(0)
def main():
    start = time.time()
    """Code in here runs only when this module is run directly"""
    FigureQueue.put(1)
    TapHistplots()
    while threading.activeCount()>1:
        time.sleep(1)
        print 'waiting on %d threads\n' % (threading.activeCount()-1),
    print '%ds elapsed' % (time.time()-start)

if __name__ == '__main__':
    main()

任何帮助都非常感谢。

相关问题:

2 个回答

6

对于 pylab 接口,有一个解决方案是 使用线程进行异步绘图

如果不使用 pylab,那么每种 matplotlib 的后端(比如 Qt、GTK、WX、Tk)可能会有不同的解决办法。问题在于,每个图形用户界面(GUI)工具包都有自己的主循环。你可以看看 ipython 是怎么处理这个问题的。

33

为什么不直接使用多进程呢?根据你的描述,线程对你来说帮助不大……

Matplotlib已经可以使用多线程,这样你就可以同时显示和操作多个图形。如果你想在多核机器上加快批处理的速度,不管怎样你都需要用到多进程。

这里有个简单的例子(警告:这会在你运行的目录下创建20个小的 .png 文件!

import multiprocessing
import matplotlib.pyplot as plt
import numpy as np

def main():
    pool = multiprocessing.Pool()
    num_figs = 20
    input = zip(np.random.randint(10,1000,num_figs), 
                range(num_figs))
    pool.map(plot, input)

def plot(args):
    num, i = args
    fig = plt.figure()
    data = np.random.randn(num).cumsum()
    plt.plot(data)
    plt.title('Plot of a %i-element brownian noise sequence' % num)
    fig.savefig('temp_fig_%02i.png' % i)

main()

撰写回答