[Tkinter-discuss] Get value instead of PY_VAR

Russell E. Owen rowen at uw.edu
Sat Nov 16 00:29:26 CET 2013


In article <5284F448.7050308 at codebykevin.com>,
 Kevin Walzer <kw at codebykevin.com> wrote:

> I'm going around in circles trying to serialize some app configuration 
> data in my Tkinter app via pickle, and I'd appreciate some help.
> 
> I set various app configurations via checkboxes and StringVar(). 
> Sometimes the value of one of the checkboxes is lost and when I try to 
> print the value, I get PY_VAR#2 instead. Here's a relevant snippet 
> setting the values:
> 
>          self.copytext= StringVar()
>          self.copytext.set(self.defaults['copytext'])
> 
>         self.whoischeck = Tile.Checkbutton(self.whoisframe, 
> variable=self.whois, text='Display Raw Whois Output')
> 
> And here's the snippet that retrieves the value:
> 
>      self.defaults['copytext'] = self.copytext
> 
> Using this call, printing the value of self.defaults['copytext'] results 
> in PY_VAR#2, which doesn't actually retain the value of the var I'm 
> setting (1 or 0). It also results in a error when I try to serialize the 
> data, because pickle can't handle this type of data:
> 
>   Can't pickle 'tkapp' object: <tkapp object at 0x01FCB090>
> 
> I can actually get the correct value if I change one call as follows:
> 
> self.defaults['copytext'] = self.copytext.get()
> 
> But then, trying to pickle this value, I get this error:
> 
> 'str' object has no attribute 'get'
> 
> What's the right way in Tkinter to get the value of a StringVar() from a 
> checkbutton, and then serialize the value via pickle?
> 
> Sometimes I can get this to work, but I don't understand the underlying 
> dynamics of it; the intersection of Python objects and Tcl variables 
> gives me headaches. I am especially unclear why I get PY_VAR rather than 
> the value in some instances, but not others.

StringVar and its kin are variable containers. You can pass them around 
as you like, but you have to be careful to always change the contained 
value using set and retrieve the contained value using get. (You can 
also assign callbacks to monitor changes, which is great.).

However, apparently you can't pickle a StringVar and you want to pickle 
the defaults dict, so it sounds like the best thing is to save the 
value, not the container in the defaults dict.

  self.defaults["copytext"] = self.copytext.get()

You then say you cannot even pickle the dict even if you do that. That 
suggests the value returned by get is not a python string, but some kind 
of wrapper class that acts like a string. If so, all you have to do is 
cast it:
  self.defaults["copytext"] = unicode(self.copytext.get())

-- Russell

P.S. you might consider json instead of pickle because the file format 
is easy to read and edit, which can be a feature for preference files.



More information about the Tkinter-discuss mailing list