0

我正在运行一个 Tkinter 脚本,它每 5 秒更新一次绘图。它调用每 5 秒绘制一次的函数。在没有那么长时间 python 开始使用大量内存之后,我检查了任务管理器。内存使用量一直在快速增长。它每 24 小时启动一个新文件,因此文件中的行数有限制。该文件开始为空。

我尝试增加 5s 的时间跨度,但它做同样的事情。也许慢一点,也尝试过每 3 行左右绘制一次,但同样的事情又发生了。

知道是什么导致了如此高的内存使用率以及如何解决吗?

谢谢!

data = np.genfromtxt(filename)

time_data = data[:,0]
room_temp_data_celsius = data[:,1]
rad_temp_data_celsius = data[:,2]
fan_state_data = data[:,3]
threshold_data = data[:,4]
hysteresis_data = data[:,5]

threshold_up = [] #empty array
threshold_down = []#empty array

for i in range(0,len(threshold_data)):
    threshold_up.append(threshold_data[i]+hysteresis_data[i])
    threshold_down.append(threshold_data[i]-hysteresis_data[i])

# Time formatting
dts = map(datetime.datetime.fromtimestamp, time_data)

fds = matplotlib.dates.date2num(dts)

hfmt = matplotlib.dates.DateFormatter('%H:%M')

# Temperature conversion
room_temp_data_fahrenheit = map(celsius_to_fahrenheit, room_temp_data_celsius)
rad_temp_data_fahrenheit = map(celsius_to_fahrenheit, rad_temp_data_celsius)
threshold_data_fahrenheit = map(celsius_to_fahrenheit, threshold_data)
threshold_up_fahrenheit = map(celsius_to_fahrenheit, threshold_up)
threshold_down_fahrenheit = map(celsius_to_fahrenheit, threshold_down)


f = plt.figure()
a = f.add_subplot(111)

a.plot(fds,room_temp_data_fahrenheit, fds, rad_temp_data_fahrenheit, 'r')
a.plot(fds,fan_state_data*(max(rad_temp_data_fahrenheit)+4),'g_')
a.plot(fds, threshold_up_fahrenheit, 'y--') 
a.plot(fds, threshold_down_fahrenheit, 'y--')

plt.xlabel('Time (min)')
plt.ylabel('Temperature '+unichr(176)+'F')
plt.legend(["Room Temperature","Radiator","Fan State","Threshold Region"], loc="upper center", ncol=2)
plt.ylim([min(room_temp_data_fahrenheit)-5, max(rad_temp_data_fahrenheit)+5])
plt.grid()


a.xaxis.set_major_formatter(hfmt)


data_graph = FigureCanvasTkAgg(f, master=root)
data_graph.show()
data_graph.get_tk_widget().grid(row=6,column=0, columnspan=3)    
root.after(WAIT_TIME, control)
4

1 回答 1

0

从您的代码中我不清楚您的情节如何随时间变化。因此,我对您现有的代码没有任何具体建议。然而,这里是一个如何在 Tkinter 应用程序中嵌入动画 matplotlib 图形的基本示例。一旦你了解它是如何工作的,你应该能够适应你的情况。

import matplotlib.pyplot as plt
import numpy as np
import Tkinter as tk
import matplotlib.figure as mplfig
import matplotlib.backends.backend_tkagg as tkagg
pi = np.pi
sin = np.sin

class App(object):
    def __init__(self, master):
        self.master = master
        self.fig = mplfig.Figure(figsize = (5, 4), dpi = 100)
        self.ax = self.fig.add_subplot(111)
        self.canvas = canvas = tkagg.FigureCanvasTkAgg(self.fig, master)
        canvas.get_tk_widget().pack(side = tk.TOP, fill = tk.BOTH, expand = 1)
        self.toolbar = toolbar = tkagg.NavigationToolbar2TkAgg(canvas, master)
        toolbar.update()
        self.update = self.animate().next
        master.after(10, self.update) 
        canvas.show()

    def animate(self):
        x = np.linspace(0, 6*pi, 100)
        y = sin(x)
        line1, = self.ax.plot(x, y, 'r-')
        phase = 0
        while True:
            phase += 0.1
            line1.set_ydata(sin(x + phase))
            newx = x+phase
            line1.set_xdata(newx)
            self.ax.set_xlim(newx.min(), newx.max())
            self.ax.relim()
            self.ax.autoscale_view(True, True, True) 
            self.fig.canvas.draw()
            self.master.after(10, self.update) 
            yield

def main():
    root = tk.Tk()
    app = App(root)
    tk.mainloop()

if __name__ == '__main__':
    main()

这里的主要思想是plt.plot应该只调用一次。它返回一个Line2D对象,line1。然后,您可以通过调用line1.set_xdata和/或来操纵绘图line1.set_ydata。这种动画“技术”来自Matplotlib Cookbook

技术说明:

这里使用了生成器函数animate来允许保存和更新绘图的状态,而不必在实例属性中保存状态信息。请注意,重复调用的是生成器函数的next方法(不是生成器):self.animate

    self.update = self.animate().next
    master.after(10, self.update) 

self.animate()因此,我们通过调用生成器's, next 方法逐帧推进情节。

于 2012-12-21T22:43:26.907 回答