Confusing problem between Tkinter.Intvar() and self declared variable class

Peter Otten __peter__ at
Tue Jan 27 10:48:07 CET 2004

Marc wrote:

> Hi all,
> I was using Tkinter.IntVar() to store values from a large list of
> parts that I pulled from a list. This is the code to initialize the
> instances:
>     def initVariables(self):
>         self.e = IntVar()
>         for part, list in info.masterList.items():
>             obj = setattr( self.e, part, IntVar() )

It seems odd to use an IntVar as a container for IntVar instances.
obj will always be set to None; just use setattr().

> That allowed me to save bundles of info without having to create
> another large dictionary or list. I was using the variable in entry

A Python object is just a dictionary in disguise.

> boxes to store the amount of parts ordered:
>      Entry( cscGroup.interior(), width=3, textvariable =
> getattr(self.e, part),
>                            text=e.get()).grid(row=x, column=2, padx=4
> )
> However, I ran into problems when I tried to pickle the instances in
> order to recall them later. To fix that problem I created my own
> simple data class that allowed me to save the data the same way while
> also having the ability to pickle it:
> class DataVar:
>     def __init__(self):
> = 0
>         self.partName = ""
>     def set(self, value):
> = value
>     def get(self):
>         return
> But I just discovered another problem. It doesn't appear to hold data
> the same way. The information appeared global when it was IntVar().
> Now when I go outside the class that set up the entry boxes, the
> information does not appear to be in DataVar. I print out the info the
> following way:
>     def printValues(self):
>         for part, list in info.masterList.items():
>             e = getattr(self.e, part)
>             print str(part) + " --->" + str( e.get() )
> This function is in the same class that initialized the DataVar
> variables and also that called the class that setup the window to
> enter the amount of parts. When I call that class I pass in the
> variable in the following way:
>        spares = Spares(self.master, self.e)
> So obviously there's something about Tkinter that causes the info to
> be global. But even though the DataVar class is an independent class,
> for some reason the information is not being maintained.
> Does anyone have any idea why this is happening and how to fix it?

I wasn't able to completely follow the last part of your post, so below is a
working version of what I /think/ you are trying to do. The important part
is a pickle-enhanced container for IntVars that stores their values instead
of the instances. It could easily be enhanced to support, say, StringVar by
inspecting the type of the values in the __setstate__() method.

import Tkinter as tk
import pickle

class Namespace:

class IntVars:
    """ Every attribute is suposed to be a TKinter.IntVar instance """
    def __getstate__(self):
        d = dict(self.__dict__)
        for k in d:
            d[k] = d[k].get()
        return d
    def __setstate__(self, d):
        for k, v in d.iteritems():
            iv = tk.IntVar()
            setattr(self, k, iv)

info = Namespace()

info.masterDict = {
    "bird": 1,
    "elephant": 2,
    "crocodile": 3,

FILENAME = "crocodile.pickle"

class LoadError(Exception): pass

class Main(tk.Frame):
    def __init__(self, master=None):
        tk.Frame.__init__(self, master)
        except LoadError:

    def loadVariables(self):
            f = file(FILENAME)
        except IOError:
            raise LoadError
            # error handling is *incomplete*
                self.e = pickle.load(f)

    def saveVariables(self):
        f = file(FILENAME, "wb")
            pickle.dump(self.e, f)

    def initVariables(self):
        self.e = IntVars()
        for part, lst in info.masterDict.iteritems():
            iv = tk.IntVar()
            setattr(self.e, part, iv)

    def initControls(self):
        interior = self # cscGroup.interior()
        x = 0
        for part, lst in info.masterDict.iteritems():
            e = tk.Entry(interior, width=3,
                textvariable=getattr(self.e, part)) # text=... has no effect
            e.grid(row=x, column=2, padx=4)
            x += 1

        self.button = tk.Button(self, text="Save values",
        self.button.grid(row=x, column=2, padx=4)

m = Main()


More information about the Python-list mailing list