Printing Varable Names Tool.. Feedback requested.

Ron_Adam radam2 at tampabay.rr.com
Thu Mar 31 21:02:56 EST 2005



Fixed it so it now runs from the command line and from winpython as
well as idle in Python 2.4 on Windows Xp.  I still don't know about
linux systems.

I decided on viewnames.py as the filename and viewit() as the calling
name.  



#---start---

# viewnames.py
"""
A utility to print the value of variables for
debugging and instructional purposes.

To use:
    from viewnames import viewit
    viewit()
    
Insert it in the program where you want to examine names.
It will pause after it prints so that it will work in loops.

Author: Ronald Adam
"""

import sys
if __name__ is not '__main__':
    import __main__ 
    
def readnames():
    """
    Build a sequential name list and a dictionary of
    objects and name references by groups.
    """
    objdict = {}        # Collect references to object.
    namelist = []       # List of names and values by frame.
    n = 2
    name = None
    while name not in ['runcode', 'RunScript', chr(63)]:
        # Move up in the frames to gather name data.
        # until the application global frame is reached.
        name = sys._getframe(n).f_code.co_name
        #print name
        namelst = [name,[]]
        namespace = sys._getframe(n).f_locals
        keys = namespace.keys()
        # Get all the names in this frame.
        for k in keys:
            try:
                trash = objdict[id(namespace[k])][name]
            except:
                try:
                    objdict[id(namespace[k])][name]=[k]
                except:
                    objdict[id(namespace[k])]={name:[k]}
            else:
                objdict[id(namespace[k])][name].append(k)
            namelst[1].append((k,namespace[k],id(namespace[k])))
            # Read any attributes if there is a dictionary.
            attribs = None
            try:
                attribs = namespace[k].func_dict
            except:
                pass
            if attribs:
                for att in attribs:
                    attname = k+'.'+att
                    try:
                        trash = objdict[id(attribs[att])][attname]
                    except:
                        try:
                            objdict[id(attribs[att])][name]=[attname]
                        except:
                            objdict[id(attribs[att])]={name:[attname]}
                    else:

objdict[id(attribs[att])][name].append(attname)

namelst[1].append((attname,attribs[att],id(attribs[att])))
        namelist.append(namelst)                
        n += 1
    return objdict, namelist

def sortnocase(stringlist): 
    tupleList = [(x[0].lower(), x) for x in stringlist]
    tupleList.sort()
    return [x[1] for x in tupleList]
            
def printnames( objdict, namelist):
    """
    Now print what we collected.
    """
    namelist.reverse()      #  Reverse it so we have globals at the
top.
    tab = 0
    for gname, group in namelist:        
        # Print group name.
        if gname == chr(63):        # Idle uses this as name as
app-globals.
            gname = 'globals'
        if gname == namelist[-1:][0][0]:
            gname = 'locals:'+gname     # Indicate locals group.
        print '%s[%s]'%('    '*tab, gname)
        tab += 1

        # Print group items.
        # Sort group fist.
        group = sortnocase(group)
        for name, obj, objid in group:
            
            # Print the varable name
            print '    '*tab,name,'-->',

            # Print object
            # Remove & replace a lot of clutter as we print it.
            # List other names pointing to mutable objects.
            obj2 = obj         # Make a copy to edit if needed.
            if name == '__doc__':
                if len(str(obj))>30:
                    obj2 = obj2.strip()
                    obj2 = '"'+obj2[:6]+' ... '+obj2[-6:]+'"'
                #obj = '<docstring>'
            if 'module' in str(obj):    # These remove clutter
                obj2 = '<module>'        # More probably needs to be
            if 'function' in str(obj):  # done here.
                obj2 = '<function>'

            # Print the object
            print obj2,

            # Print the other names pointing to
            # the object.
            endofline = ''
            # If object is immutable, don't print references.
            if type(obj) not in [int, str, float, bool, tuple] \
                   and obj not in [True, False, None]:
                for key in objdict[objid].keys():
                    grp = key
                    if key == chr(63):
                        grp = 'globals'
        
                    namegroup = objdict[objid][key]
                    n = 0
                    for nm in namegroup:                        
                        if nm != name:
                            if n>0:
                                endofline += ', '
                            if grp != gname:
                                endofline += grp+':'+nm
                            else:
                                endofline += nm
                            n += 1
                                
                if len(endofline)>0:
                    endofline = '<-- '+endofline
            print endofline
                
def viewit():
    """ Show current names """
    objdict, namelist = readnames()
    print
    printnames( objdict, namelist)
    print
    raw_input('Press enter to continue.')


"""
A few nonsense test functions.
"""
def test1():
    global g
    t = g
    t = [9]
    test2.at1 = [True]
    test2(t)
    
def test2(w):
        a = glist
        aaa = test2.at1
        test2.at1[0] = True
        a[0] = 'a changed'
        w[0] = 'altered'
        viewit()

        
if __name__ == '__main__':
    # Make a few globals to see.
    g = 45
    h = g
    glist = ['just a','list']

    # Put an attribute on a function
    # to find.
    test2.at1 = 25

    # Run test function.
    test1()

#---end---



More information about the Python-list mailing list