我有一个处理Modbus通信的Python脚本。我添加的一个特性是一个“图形”,它显示响应时间以及一条彩色编码线,指示响应是成功的、有异常的还是错误的。这个图形只是Tkinter的一个可滚动的画布小部件。在
在绘制一定数量的线后,旧的线将被删除,然后在末尾添加一个新的。对于本例,我将其设置为10,这意味着画布上一次的行数永远不会超过10行。在
代码正常工作,但此函数中存在内存泄漏。我让它运行了大约24小时,24小时后占用了大约6倍的内存。函数是一个较大类的一部分。在
我目前的猜测是,我的代码导致画布大小不断“膨胀”,这会慢慢消耗内存。在
self.lineList = []
self.xPos = 0
def UpdateResponseTimeGraph(self):
if not self.graphQueue.empty():
temp = self.graphQueue.get() #pull from queue. A separate thread handles calculating the length and color of the line.
self.graphQueue.task_done()
lineName = temp[0] #assign queue values to variables
lineLength = temp[1]
lineColor = temp[2]
if len(self.lineList) >= 10: #if more than 10 lines are on the graph, delete the first one.
self.responseTimeCanvas.delete(self.lineList[0])
del self.lineList[0]
#Add line to canvas and a list so it can be referenced.
self.lineList.append(self.responseTimeCanvas.create_rectangle(self.xPos, self.responseWidth, self.xPos + 4, self.responseWidth-lineLength,
fill=lineColor, outline=''))
self.xPos += 5 #will cause the next line to start 5 pixels later. MEMORY LEAK HERE?
self.responseTimeCanvas.config(scrollregion=self.responseTimeCanvas.bbox(ALL))
self.responseTimeCanvas.xview_moveto(1.0) #move to the end of the canvas which is scrollable.
self.graphFrame.after(10, self.UpdateResponseTimeGraph)
一种解决方案是,一旦达到极限,就可以循环回图的开头,但我不想这样做,因为这可能会混淆图形的起始位置。通常我收到的回复远远多于10条。在
编辑:
我仍在做跟踪和错误的工作,但看起来只要行属性不通过itemconfig更改,那么内存泄漏就可以通过Bryan的建议消除。下面的代码应该可以按原样运行,如果您使用的是python2.7,请将import语句从tkinter更改为tkinter(小写与大写t)。这个代码会有内存泄漏。注释掉itemconfig行,它将被删除。在
^{pr2}$
这是没有内存泄漏的代码。泄漏的最初来源是我删除了旧的行,然后创建了一个新的。此解决方案首先将行移到末尾,然后根据需要更改其属性。在我的示例代码中,我有第二个“泄漏”,每次我都随机选择一个颜色,这导致使用的颜色数量会占用大量内存。此代码只打印绿线,但长度是随机的。在
底层tk画布不会重用或回收对象标识符。无论何时创建新对象,都会生成一个新的标识符。这些物体的记忆永远不会被回收。在
注意:这是嵌入式tcl解释器中的内存,而不是python管理的内存。在
解决方案是重新配置旧的、不再使用的元素,而不是删除它们并创建新的元素。在
相关问题 更多 >
编程相关推荐