[Tkinter-discuss] Leak with Entry on Mac ( 8.5.7 / 2.6.2 )?

Art Botterell acb at incident.com
Sat Jun 6 07:17:56 CEST 2009


Hi, new Python/Tkinter adopter here!

I'm building a little screen display to show status of a remote device  
(a radio scanner) in an MVC pattern.  In the top-level "view" GUI  
object I'm updating the text in three Entry fields and the background  
color of a Frame, all at a rate of about five cycles per second.   
Works fine except it leaks memory at a rate of between 1-2K per second.

As best I can tell the problem seems to be down in Tkinter: I can pass- 
out the set() calls to the StringVars and the color update and leave  
everything else and my memory consumption stablizes.  I can also  
induce a leak by making get()s.  I tried bypassing the StringVar  
mechanism and doing delete()/insert() directly on the Entry widgets...  
that didn't seem to solve it either.

Googling around I can see that there've been various memory leak  
issues in past history, but I don't see any open issues with 8.5.7 and/ 
or Python 2.6.2.  So I wonder if maybe I'm just making a noobish  
mistake in my own code (please see below.)

I'm admitting my helplessness and pleading for help.  TIA!

- Art


#! /usr/bin/env python

'''
Created on June 5, 2009

@author: acb
'''

from Tkinter import *
import tkFont
import time
import Controller
import threading
import sys
import signal


class Display:

     def shutdown(foo):
         sys.exit()

     def __init__(self, root):

         # define display fonts
         self.sans1 = tkFont.Font( family="sanserif", size=24)
         self.sans2 = tkFont.Font( family="sanserif", size=12)

         # shutdown on window close and on control-c
         root.protocol("WM_DELETE_WINDOW", self.shutdown)
         def exit_handler( signal, frame ): self.shutdown()
         signal.signal(signal.SIGINT, exit_handler)

         # Set up the display frame and fields
         self.toppad = Frame(root, height=4)
         self.toppad.pack()

         self.display = Frame(root)

         self.indisplay = Frame(self.display, background="#ffffff")

         self.spacer = Frame(self.indisplay, height=5)
         self.spacer.pack(expand=YES)

         self.freq = Entry(self.indisplay)
         self.freqString = StringVar()
         self.freq.config(justify=CENTER, font=self.sans2,  
borderwidth=0, textvariable=self.freqString)
         self.freq.pack(padx=10, pady=5)

         self.label = Entry(self.indisplay)
         self.labelString = StringVar()
         self.label.config(justify=CENTER, font=self.sans1,  
borderwidth=0, width=12, textvariable=self.labelString)
         self.label.pack(padx=10, pady=5)

         self.object = Entry(self.indisplay)
         self.objectString = StringVar()
         self.object.config(justify=CENTER, font=self.sans2,  
borderwidth=0, textvariable=self.objectString)
         self.object.pack(padx=10, pady=5)

         self.spacer = Frame(self.indisplay, height=5)
         self.spacer.pack(expand=YES)

         self.indisplay.config()
         self.indisplay.pack( fill=BOTH, padx=2, pady=2 )

         self.display.pack(fill=BOTH, padx=5)

         # Set up controls
         self.control = Canvas(root)
         self.keycode = 0

         self.manBtn = Button(self.control, text="Manual")
         self.manBtn.pack(side=LEFT,padx=20)
         self.manBtn['command']=lambda: self.keyset(3)

         self.upBtn = Button(self.control, text="Up")
         self.upBtn.pack(side=LEFT,expand=YES,padx=10)
         self.upBtn['command']=lambda: self.keyset(7)

         self.dnBtn = Button(self.control, text="Dn")
         self.dnBtn.pack(side=LEFT,expand=YES,padx=10)
         self.dnBtn['command']=lambda: self.keyset(9)

         self.scnBtn = Button(self.control, text="Scan")
         self.scnBtn.pack(side=RIGHT,padx=20)
         self.scnBtn['command']=lambda: self.keyset(15)

         self.control.pack(fill=X, ipady=2, pady=4)

         self.controller = Controller.Controller(self)

     # command to send a keystroke to the scanner
     def keyset(self, value):
         self.controller.send_key(value)


     # commands to update the display fields (called from the  
controller)
     def set_freq(self, text): self.freqString.set(text)
     def set_label(self, text): self.labelString.set(text)
     def set_object(self, text): self.objectString.set(text)
     def set_color(self, text): self.display['background']=text


root = Tk()
disp = Display(root)
root.wm_title("PSR-600 Remote v0.4")
root.mainloop()
  
        



More information about the Tkinter-discuss mailing list