matplotlib在简单的线程中绘制冻结

Lui*_*des 4 python plot multithreading matplotlib freeze

一直在玩Python的绘图库,并且遇到了matplotlib,它似乎已经过战斗测试和验证.但是我在线程中创建一个简单的绘图时遇到了一个问题.

在下面的示例中,Dummyplotme方法连续两次在一个线程中运行,但在第二次迭代中它被卡住/冻结.很可能是明显的并且与线程本身有关,但到目前为止我没有发现它.

import matplotlib.pyplot as plt
from numpy import arange, sin, pi
import threading

class Dummy():

    def plotme(self, iteration = 1):

        print "%ix plotting... " % iteration,
        t = arange(0.0, 2.0, 0.01)
        s = sin(2*pi*t)
        plt.plot(t, s)
        plt.xlabel('time (s)')
        plt.ylabel('voltage (mV)')
        plt.title('About as simple as it gets, folks')
        #savefig("test.png") # irrelevant here
        plt.close()

    def threadme(self, iteration = 1):

        thread_plot = threading.Thread(target=self.plotme,
                                      args=(iteration,))
        thread_plot.start()
        thread_plot.join()

dummy = Dummy()
dummy.threadme(1)
dummy.threadme(2)
Run Code Online (Sandbox Code Playgroud)

Tho*_*anz 5

首先,请注意 - 接口pyplot不是线程安全的.

然后:使用"Agg"-backend进行非交互式创建多个图像.

一个工作示例(由于线程可能出现问题)是:

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from numpy import arange, sin, pi
import threading

class Dummy():

    def plotme(self, iteration = 1):

        print "%ix plotting... " % iteration,
        t = arange(0.0, 2.0, 0.01)
        s = sin(2*pi*t)
        plt.plot(t, s)
        plt.xlabel('time (s)')
        plt.ylabel('voltage (mV)')
        plt.title('About as simple as it gets, folks')
        plt.savefig("19110942_%i_test.png" % iteration) # irrelevant here
        plt.clf()

    def threadme(self, iteration = 1):

        thread_plot = threading.Thread(target=self.plotme,
                                      args=(iteration,))
        thread_plot.start()
        thread_plot.join()

dummy = Dummy()
dummy.threadme(1)
dummy.threadme(2)
Run Code Online (Sandbox Code Playgroud)

线程安全版本看起来像这样:

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from numpy import arange, sin, pi
import threading

class Dummy():

    def plotme(self, iteration = 1):

        print "%ix plotting... " % iteration,
        t = arange(0.0, 2.0, 0.01)
        s = sin(2*pi*t)

        fig, ax = plt.subplots()
        ax.plot(t, s)
        ax.set_xlabel('time (s)')
        ax.set_ylabel('voltage (mV)')
        ax.set_title('About as simple as it gets, folks (%i)' % iteration)
        fig.savefig("19110942_%i_test.png" % iteration)

    def threadme(self, iteration = 1):

        thread_plot = threading.Thread(target=self.plotme,
                                      args=(iteration,))
        thread_plot.start()
        thread_plot.join()

dummy = Dummy()
dummy.threadme(1)
dummy.threadme(2)
Run Code Online (Sandbox Code Playgroud)

  • 注意:过去几天我一直在玩这个,并且可以有信心地说上面的第二个版本并不比第一个更“线程安全”,两者都会很高兴地挂在后续的线程运行中,**如果`matplotlib.use('Agg')` 没有被调用**。关键是使用非交互模式,然后两者都会在一个线程中愉快地运行很多很多次而不会出错。 (2认同)
  • **交互式**绘图的任何线程安全选项? (2认同)