python pickle, __getstate__, setstate__ problem

ed_tsang at yahoo.com ed_tsang at yahoo.com
Mon Apr 23 16:54:08 EDT 2001


I have a problem about my script in initializeing the class attribtes 
and, pickle them and load them back again in the next invokation.

Here is some backgrond:

The script that I wrote is for drawing the primitives, received from 
and sent to the Implementation under test. The reason I am using 
pickle is to store the state of the Gui, like all the data user 
entered to the script, so that when the scirpt got invoked again, the 
ser do not need to reenter te again. All the states are stores as 
class attributes in class GuiState.

To remember  the last known state of Gui. Class Gui either load the 
the last known instance of GuiState State through using python pickle
or create a new instance when that failed or the first time the 
script is invoked. When the suer click on quit, that will invoke the 
quit function of class Gui. Class Gui will then update all the class 
GuiState attributes through calling the updateAttribute of class 
GuiState. Then store the object as persistence objects through 
calling pickle.dump.  
But I ran into two problems:
1. whenever some of the states are not given values (e.g. user no 
selecting a input file or output file) the whole script hangs on 
quit. I traced that to inside the function of updateAttribute of 
Class Gui State when it try to append the elements of inputFileList 
to self.inputFileList, it will have an infinite loop!!! That is why I 
comment those lines out. But without actually copying the contents, I 
doubt the Class GuiState will get the values of the attributes, as I 
suspect what I am doing in the code that I sent you just copy the 
reference which will be destroyed afer the porcess exists ....
I print out the list of inputFileList & outputFileList:
  
inputFile List ['/la02/qa/etsang1/ts/9005016/modules/gui/1']

outputFileList [<Tkinter.StringVar instance at 124960>]
outputFileList has nothing in it as no outputFile has been 
selected.  .....
Thatlets me suspect if the way I initialise the two list simply but 
assigning [] to them in the init mehtod of Class GuiState is correct 
or not ... signed ....

2. when some of the attributes are not set during the last invokation 
of script, even though they are initiliazed. There seems to have 
problem in loading them back in through pickle. Instead of getting 
attributes that contain the initilized values, an istance is returned 
cauaing error!! Sample error message when when user does not set 
self.type as below, even though they have been set as zero before:

Exception in Tkinter callback
Traceback (innermost last):
  File "/sd/ps/alexma/proj/ntharn/lib/python1.5/lib-tk/Tkinter.py", 
line 764, in __call__
  File "msggen.py", line 284, in buildMSC
    value = self.type.get()
  File "/sd/ps/alexma/proj/ntharn/lib/python1.5/lib-tk/Tkinter.py", 
line 119, in get
ValueError: invalid literal for int(): PY_VAR5
start shelf attributes
end self inputName and outputName
['/la02/qa/etsang1/ts/9005016/modules/gui/1'] [<Tkinter.StringVar 
instance at 124960>]
end shelf all attributes
[1]  + Terminated           python msggen.py

Acutally I suspect the attributes have been shelved at all .... as 
when the program loads and try to get the values, it found an 
istance!! as shown in above error message!!

Can someone kindly have a look at the the way I shelf, relaod  the 
attributes?? Or are they due to another problem. I know thisis a long 
posting .. but not many people seems to know pickle nor python on my 
end to provide assitance. 

Thanks

Below is the code: the new stuff is marked by ####


from Tkinter import *
from tkFileDialog import *
from Dialog import Dialog
import re
import string
import time
import os
import stat
import math
# to preserve class instance attributes
import pickle


def makeMenu(gui):
    # make menu button : "File"
    File_button = Menubutton(gui.menuframe, text='File', underline=0)
    File_button.grid(row=0, column=0, sticky=W)
    tempText = Text()
    color = tempText.cget('background')
    Dummy_button = Menubutton(gui.menuframe, width=63, 
activebackground=color, highlightcolor='Blue',text='', underline=0)
    Dummy_button.grid(row=0, column=1, sticky=W)
    Dummy_button.menu = Menu(Dummy_button)
    File_button.menu = Menu(File_button)
    
    File_button.menu.add_command(label='Open Test Log ...', 
underline=0, 
				 command=gui.openfile)

    File_button.menu.add_command(label='Save Message Sequence 
Chart...', underline=0, 
				 command=gui.save)

    File_button.menu.add('separator')

    File_button.menu.add_command(label='Quit', underline=0, 
				 command=gui.quit)

    File_button['menu'] = File_button.menu
    gui.menuframe.tk_menuBar(File_button, Dummy_button)

def getTabs(line):
    num=0
    for char in line:
        if (char != '\t'):
            break
        num=num+1
    return(num)

######################################################333
# customer object to hold the state of class Gui
class GuiState:
    def __init__(self):
        self.inputName = StringVar()
        self.outputName = StringVar()
        self.inputName.set("")
        self.outputName.set("")
        self.inputFileList = []
        self.outputFileList = []
        self.stackname = StringVar()
        self.stackname.set("")
        self.name = StringVar()
        self.iut = StringVar()
        self.name.set("")
        self.iut.set("")
        # define all buttons
        self.type = IntVar()
        self.type.set(0)
    # return data representaton for pickled object
    def __getstate__(self):
        oldDict = self.__dict__ # get attribute dictionary
        del oldDict['inputName']
        del oldDict['outputName']
        del oldDict['inputFileList']
        del oldDict['outputFileList']
        del oldDict['stackname']
        del oldDict['name']
        del oldDict['iut']
        del oldDict['type']
        return oldDict
    # restore object state from data representation generated by 
_getstate__  
    def __setstate__(self,dict):
        self.inputName = open(dict['inputName'])
        self.outputName = open(dict['outputName'])
        self.inputFileList = open(dict['inputFileList'])
        self.outputFileList = open(dict['outputFileList'])
        self.stackname = open(dict['stackname'])
        self.name = open(dict['name'])
        self.iut = open(dict['iut'])
        self.type = open(dict['type'])
    def updateAttribute
(self,inputName,outputName,stackname,name,iut,type,inputFileList,outpu
tFileList):
        print "start shelf attributes"
        self.inputName.set(inputName)
        self.outputName.set(outputName)
        print "end self inputName and outputName"
        print inputFileList, outputFileList
        #if inputFileList != []:
        #   print "shelf nonempty inputFileList"
        #   map(self.inputFileList.append,inputFileList)
        #   print "end shelf inputFileList"
        #else:
        #   print "self empty inputFileList"
        #   self.inputFileList = []
        #if outputFileList !=  []:
        #   print "self nonempty outputFileList"
        #   map(self.outputFileList.append,outputFileList)
        #   print "end self outputlist"
        #else:
        #   self.outputFileList = []
        self.inputFileList = inputFileList
        self.outputFileList = outputFileList
        
        self.stackname.set(stackname)
        self.name.set(name)
        self.iut.set(iut)
        self.type.set(type)
        print "end shelf all attributes"
        return 
###################### END NEW#############################        
class Gui:
	
    def __init__(self, master, img):
        self.master = master;
        # define each frame
        #   main frame is at the very top
        #   button frame is the command button frame
        #   list frame is used for all of the list boxes
        #   quit frame is used for the quit button
        self.headerframe = Frame(self.master, width = 80)
        self.headerframe.grid(row=0, column=0, sticky='W')
        self.menuframe = Frame(self.headerframe, relief=RAISED,
            borderwidth=2, width = 80)
        self.menuframe.grid(row=0, column=0, sticky='W')
        makeMenu(self)
        self.logoframe = Frame(self.headerframe, width = 80)
        self.logoframe.grid(row=0, column=0, sticky='E') 
        # column affects locaton of logo
        self.buttonframe = Frame(self.master, width = 80)
        self.buttonframe.grid(row=1, column=0, sticky='W')
        self.octetframe = Frame(self.master, width = 80)
        self.octetframe.grid(row=2, column=0, sticky='W')
        
        self.octetframe2 = Frame(self.master, width = 5)
        self.octetframe2.grid(row=80, column=0, sticky='W')
        
        self.listFrame = Frame(self.master, width = 80)
        self.groupsList = Frame(self.listFrame, width = 50)
        self.groupsList.grid(row=0, column=0, sticky=N)
        # intialize Gui state class
        try:  
        # depersist and display an object
          self.stateObj = pickle.load(open("msc.dat","rb"))
        except:
        ########################## NEW  START #######################
        # invoke the first time
          self.stateObj = GuiState()
        
        self.inputName = StringVar()
        self.outputName = StringVar()
        self.inputName.set(self.stateObj.inputName)
        self.outputName.set(self.stateObj.outputName)
        self.inputFileList = self.stateObj.inputFileList
        self.outputFileList = self.stateObj.outputFileList
        self.stackname = StringVar()
        self.stackname.set(self.stateObj.stackname)
        self.name = StringVar()
        self.iut = StringVar()
        self.name.set(self.stateObj.name)
        self.iut.set(self.stateObj.iut)
        # define all buttons
        self.type = IntVar()
        self.type.set(self.stateObj.type)
        ########################## NEW END #######################
        self.counter = IntVar()
  
        self.ie = Checkbutton(self.buttonframe,
                text="Build ALL ",
                variable=self.type, onvalue = 1, offvalue =0)
        self.ie.pack()        
        self.ie.grid(row=0, column=1, pady=10, sticky=W)

        self.build = Button(self.buttonframe,
                text="Build", command=self.buildMSC)
        self.build.grid(row=0, column=3)

        self.clear = Button(self.buttonframe,
                text="Clear", command=self.clear)
        self.clear.grid(row=0, column=4)

        # define all labels
        Label(self.logoframe, image=img).grid(row=0,column=4,sticky=E)
		
        # define all listboxes
        self.pdudfn = Text(self.octetframe,
                font='*-Courier-Bold-R-Normal-*-120-*',
                height=20,
                width=80)
        self.pdudfn.grid(row=0, column=0, sticky=W)
        self.pdudfn.tag_config('HIGHLIGHT', background="White") 

        self.pdubuild = Text(self.octetframe2,
                font='*-Courier-Bold-R-Normal-*-120-*',
                height=5,
                width=80)
        self.pdubuild.grid(row=0, column=0, sticky=W)
        self.pdubuild.tag_config('HIGHLIGHT', background="White") 
        
        # define all scrollbars
        self.pdudfn.scrollY = Scrollbar(self.octetframe,
                orient=VERTICAL)
        self.pdudfn['yscrollcommand'] = self.pdudfn.scrollY.set
        self.pdudfn.scrollY['command'] = self.pdudfn.yview
        self.pdudfn.scrollY.grid(row=0, column=1,sticky='NS')

        self.pdubuild.scrollY = Scrollbar(self.octetframe2,
                orient=VERTICAL)
        self.pdubuild['yscrollcommand'] = self.pdubuild.scrollY.set
        self.pdubuild.scrollY['command'] = self.pdubuild.yview
        self.pdubuild.scrollY.grid(row=0, column=1,sticky='NS')
   
       
    def buildMSC(self):
        value = self.type.get()
        if value == 1:
           self.buildAllMsc()
        self.saveArrows()
       

    def clear(self):
        self.pdubuild['state']=NORMAL
        self.pdubuild.delete("0.0", END)
        self.pdudfn.delete("0.0", END)
        self.pdubuild['state']=DISABLED
        filename = self.outputName.get()
        try:
           self.fd = open(filename,"w")
        except IOError:
            Dialog(self.master,
			       text="Cannot open file to clear.",
			       title="Error",
			       bitmap='error',
			       default=0,
			       strings=('OK',))
            return
        self.fd.close()
        
    def save(self, event=None):
        defaultfile = self.inputName.get()
        if self.type.get() == 1:
           Dialog(self.master,
			       text="Application is under auto mode. 
File names are self generated.",
			       title="Error",
			       bitmap='error',
			       default=0,
			       strings=('OK',))
           return
            
        outputName = asksaveasfilename(defaultextension=".arr",
            filetypes=["{Message Sequence Chart} {.arr}"], 
initialfile="%s.arr"%defaultfile ) 
        self.outputName.set(outputName)
        try:
            self.fd=open(outputName,"w");
            self.fd.close();

        except IOError:
            Dialog(self.master,
			       text="Cannot open file to save.",
			       title="Error",
			       bitmap='error',
			       default=0,
			       strings=('OK',))
            
        except:
            pass
       

    def buildFileList(self,arg,dirname,files):
        inputfile = self.inputName.get()
        if inputfile == "":
          return
        inputfile = os.path.basename(inputfile)
        
        for file in files:
            if re.search(inputfile,file): 
               fullpath= os.path.join(dirname, file)
               if fullpath[-4:] == '.arr':
                  pass
               else:
                  self.inputFileList.append(fullpath)
                  self.outputFileList.append(fullpath+'.arr')
        self.inputFileList.sort()
        self.outputFileList.sort()
        
        
        
    def openfile(self, event=None):
        try:  
       
           inputName = askopenfilename(filetypes=["{Test Log Files} 
{*}"])
                   
           if inputName == "":
              Dialog(self.master,
		 	        text="Input Log File name must be 
specified to produce arrow diagrams",
			        title="Error",
			        bitmap='error',
			        default=0,
			        strings=('OK',))
              return
           self.inputName.set(inputName)
           self.inputFileList.append(inputName)
           outputName = inputName + '.arr'
           self.outputName.set(outputName)
           self.outputFileList.append(self.outputName)
        except:
           Dialog(self.master,
		 	        text="Input Log File name must be 
specified to produce arrow diagrams",
			        title="Error",
			        bitmap='error',
			        default=0,
			        strings=('OK',))
           return
       

    def quit(self, event=None):
        ########################## NEW  START #######################
        self.stateObj.updateAttribute
(self.inputName,self.outputName,self.stackname,self.name,self.iut,self
.type,self.inputFileList,self.outputFileList)
        self.menuframe.quit()
        # persist and dump object attributes.
        pickle.dump(self.stateObj, open("msc.dat","wb"))
        ########################## NEW  END #######################


    def ctfPrint(self,string):
        
        if self.outputName.get() == "":
           self.save()
           #Open file and append string
        fd = open(self.outputName.get(),"a+")
        fd.write(string)
        self.pdudfn.insert(END, string)
        
        #Close file
        fd.close()

    def createTestList(self):
        line    = None
        
        inputfile = self.inputName.get()
        
        try:
          fd = open(inputfile, 'r')
        except IOError:
          Dialog(self.master,
			       text="Cannot open file",
			       title="Error",
			       bitmap='error',
			       default=0,
			       strings=('OK',))
          return
        # display status to stdout and status window
        stateString = "\nBuild MSC for %s"%inputfile
        print stateString
        self.pdubuild.insert(END, stateString)  
        
        trclist = fd.readlines()
        strip = string.strip
        for x in range(0,len(trclist)):
            trclist[x]=strip(trclist[x])
        fd.close()
        idx = 0
        counter = 0
        tstlist = []
        
        
        for line in trclist:
            if line == "":  # skip blank line
                continue
            if line[0] == "-":   
                counter = counter+1
                if counter == 1:
                    tstlist.append([])
            if counter > 0:
                tstlist[idx].append(line)
            if counter == 4:
                idx = idx + 1
                counter = 0
        return tstlist
    
    def getData(self):
        self.name.get()
        self.iut.get()
        self.inputWindow.destroy()
    

        
    def stackData(self):
        self.inputWindow = Toplevel(self.master)
        self.inputWindow.geometry("+%d+%d" % (self.master.winfo_rootx
()+180,
                                  self.master.winfo_rooty()+180))
        self.inputWindow.title("Enter stack data")
        Label(self.inputWindow, text ="Please enter the 2 letter 
prefix for each stack seperated by a space.").grid(row=1, 
columnspan=2, pady=2, sticky=W)
        Label(self.inputWindow, text = "There must be a minimum of 2 
stacks and a maximum of 5.").grid(row=2, columnspan=2, pady=2, 
sticky=W)
        Label(self.inputWindow, text = "The second entry is the IUT 
i.e Xx Yy Zz").grid(row=3, columnspan=2, pady=2, sticky=W)
        Label(self.inputWindow, text="Stack Names:").grid(row=4, 
sticky=W)
        self.e1 = Entry(self.inputWindow, 
textvariable=self.stackname, width=35)
        self.e1.grid(row=4, column=1, sticky="EW", pady=1)
        okButton = Button(self.inputWindow, text="Ok", 
command=self.getData)
        
        okButton.grid(row=5, column=1, sticky=W, pady=6)
       
        self.inputWindow.wait_window()  
        
    def buildAllMsc(self):
        index = 0
        
        listDir = os.getcwd()
        os.path.walk(listDir,self.buildFileList,None)
        
        if self.inputFileList != []:
          
           for file in self.inputFileList:
             
              
               self.inputName.set(file)
               self.outputName.set(self.outputFileList[index])
               self.saveArrows()
               index = index +1
               
               self.master.update()
           self.pdubuild.insert(END, "Processing Completed")
        else:
           Dialog(self.master,
		 	        text="Input Log File name must be 
specified to produce arrow diagrams",
			        title="Error",
			        bitmap='error',
			        default=0,
			        strings=('OK',))
           return 
         
    def saveArrows(self):
      
        tstList       = None
        temp          = None
        stackList     = {}
        numStacks     = None
        upper         = 0
        lower         = 0
        mngmt         = 0
        other         = 0
        columnWidth   = None
        emptySpace    = None
        arrowLine     = None
        stack         = None
        emptyLine     = None
        space         = ""
        stacknames    = ""
        upperTx       = None
        upperRx       = None
        lowerTx       = None
        lowerRx       = None
        mngmtTx       = None
        mngmtRx       = None
        otherTx       = None
        otherRx       = None
        lowerFunction = None
        upperFunction = None
        mngmtFunction = None
        otherFunction = None
        test          = None
        testList      = None
        event         = None
        eventList     = None
        line          = None
        function      = None

        if self.outputName == "":
           save()
      
        tstList = self.createTestList()
         
        if tstList == None:
           return
        
        temp = self.stackname.get()
        # first time invoked
        if self.counter.get() == 0:
           self.stackData()
           temp = self.stackname.get()
           self.counter.set(1)
        # this is no the first run, stackname should be stored already
        temp = self.stackname.get()   
        if temp == "":
           return
        # clear msc window   
        self.pdudfn.delete("0.0", END)
        
        stackList = string.split(temp)
        numStacks = len(stackList)
        upper = 0
        lower = 0
        mngmt = 0
        other = 0
        if numStacks > 2:
            lower = 2
        if numStacks > 3:
            mngmt = 3
        if numStacks > 4:
            other = 4
        columnWidth = 70/(numStacks-1)
        emptySpace = " "*columnWidth
        arrowLine = "-"*(columnWidth-1)
        stack = "|%s"%emptySpace
        emptyLine = stack*(numStacks-1) + "|\n"
        space = ""
        stacknames = ""
        for name in stackList:
            stacknames = stacknames + space + name
            space = " "*(columnWidth - len(name)+1)
        # Arrow for event travels from upper stack to the right?
        upperTx = "|%s>"%arrowLine + stack*(numStacks-2) + "|\n"
        upperRx = "|<%s"%arrowLine + stack*(numStacks-2) + "|\n"
        upperFunction = "|%s" + stack*(numStacks-2) + "|\n"
        lowerTx = stack + "|<%s"%arrowLine + stack*(numStacks-3) 
+ "|\n"
        lowerRx = stack + "|%s>"%arrowLine + stack*(numStacks-3) 
+ "|\n"
        lowerFunction = stack + "|%s" + stack*(numStacks-3) + "|\n"
        mngmtTx = stack + "|<--%s"%(arrowLine*2) + stack*(numStacks-
4) +"|\n"
        mngmtRx = stack + "|%s-->"%(arrowLine*2) + stack*(numStacks-
4) +"|\n"
        mngmtFunction = stack + "|%s" + stack*(numStacks-4) + "|\n" 
        otherTx = stack + "|<----%s"%(arrowLine*3) + stack*(numStacks-
5) +"|\n"
        otherRx = stack + "|%s---->"%(arrowLine*3) + stack*(numStacks-
5) +"|\n"
        otherFunction = stack+ "|%s" + stack*(numStacks-5) +"|\n"
        split = string.split
        strip = string.strip
        search = re.search
        
        linecounter = 0
        
        for test in tstList:
           
            evntsList = []
          
            if linecounter < 1:
               self.ctfPrint(stacknames + "\n")
               linecounter = linecounter +1

            isFunction = FALSE
            for line in test:
                if ((search( "CallFunc", line) != None) or (search
( "@event@", line) != None)):
                    wordList = split(line)
                    
                    for word in wordList :
                        if isFunction == TRUE :
                           print "Found a primitive: %s"%word
                           newLine = "Transmit    : " + word
                           evntsList.append(newLine)
                           isFunction = FALSE
                           break
                        if word == "CallFunc":
                           isFunction = TRUE
                        if (search("@event@", word)) != None :
                           word = re.sub("@event@", "", word)
                           print "Found an event: %s"%word
                           newLine = "Received    : " + word
                           evntsList.append(newLine)
                           break

            
            for event in evntsList:
                function = split(event)[2]
                extra_info = split(event, function)[1]   
                extra_info = strip(extra_info)
            
                
                if event[0:8] == "Transmit":
                 
                    if event[14:16] == stackList[upper]:
                        function = function + " "*(columnWidth-len
(function))
                        extra_info = extra_info + " "*(columnWidth-len
(extra_info))
                        self.ctfPrint(upperTx)
                        self.ctfPrint(upperFunction%function)
                        self.ctfPrint(upperFunction%extra_info)
                        self.ctfPrint(emptyLine)
                    elif event[14:16] == stackList[lower]:
                        function = " "*(columnWidth-len(function)) + 
function
                        extra_info = " "*(columnWidth-len
(extra_info)) + extra_info
                        self.ctfPrint(lowerTx)
                        self.ctfPrint(lowerFunction%function)
                        self.ctfPrint(lowerFunction%extra_info)
                        self.ctfPrint(emptyLine)
                    elif event[14:16] == stackList[mngmt]:
                        function =  emptySpace + "|" +" "*
(columnWidth-len(function)) + function
                        extra_info = emptySpace + "|" +" "*
(columnWidth-len(extra_info)) + extra_info
                        self.ctfPrint(mngmtTx)
                        self.ctfPrint(mngmtFunction%function)
                        self.ctfPrint(mngmtFunction%extra_info)
                        self.ctfPrint(emptyLine)
                    elif event[14:16] == stackList[other]:
                        function =  (emptySpace + "|")*2 +" "*
(columnWidth-len(function)) + function
                        extra_info = (emptySpace + "|")*2 +" "*
(columnWidth-len(extra_info)) + extra_info
                        self.ctfPrint(otherTx)
                        self.ctfPrint(otherFunction%function)
                        self.ctfPrint(otherFunction%extra_info)
                        self.ctfPrint(emptyLine)
                elif event[0:8] == "Received":
                   
                    if event[14:16] == stackList[upper]:
                        function = function + " "*(columnWidth-len
(function))
                        extra_info = extra_info + " "*(columnWidth-len
(extra_info))
                        self.ctfPrint(upperTx)
                        self.ctfPrint(upperFunction%function)
                        self.ctfPrint(upperFunction%extra_info)
                        self.ctfPrint(emptyLine)
                    elif event[14:16] == stackList[lower]:
                        function = " "*(columnWidth-len(function)) + 
function
                        extra_info = " "*(columnWidth-len
(extra_info)) + extra_info
                        self.ctfPrint(lowerTx)
                        self.ctfPrint(lowerFunction%function)
                        self.ctfPrint(lowerFunction%extra_info)
                        self.ctfPrint(emptyLine)
                    elif event[14:16] == stackList[mngmt]:
                        function = function + " "*(columnWidth-len
(function)) + stack
                        self.ctfPrint(mngmtRx)
                        self.ctfPrint(mngmtFunction%function)
                        self.ctfPrint(emptyLine)
                    elif event[14:16] == stackList[other]:
                        function = function + " "*(columnWidth-len
(function)) + stack*2
                        self.ctfPrint(otherRx)
                        self.ctfPrint(otherFunction%function)
                        self.ctfPrint(emptyLine)

        self.ctfPrint("hor
\n")
# Main function, run as a standalone program
def main():
    sep = os.sep
    print "Loading \n"
    root = Tk()
    tharnbase = os.environ['THARN']
     
    img = PhotoImage
(file=tharnbase+sep+'modules'+sep+'gui'+sep+'trillium.gif')
    gui = Gui(root,img)
 
    root.protocol('WM_DELETE_WINDOW', root.quit)
    root.title("TRILLIUM MSC Builder")
    root.iconname("MSCBld")
    root.mainloop()
    
    

if __name__ == '__main__':

    
    main()








More information about the Python-list mailing list