Can you obtain names from parent scope?

Pedro Rodriguez pedro_rodriguez at club-internet.fr
Sun Jan 19 06:29:30 EST 2003


On Fri, 17 Jan 2003 15:51:35 +0000, Will Sadkin wrote:

> I want to write a function that takes an arbitrary set of objects,
> and prints them in the form "name = <value>."  That is, I want to be
> able to say:
> 
>>>> a = 'hi!'
>>>> dbgval(a)
> a = hi!
>>>> b = 2
>>>> dbgval(b)
> b = 2
> 
> However I can't make this work, because objects don't have any
> intrinsic name, and if I write a function of the form
>>>> def dbgval(*args):
>     ...
> 
> then dbgval() only knows the arguments objects as belonging to the
> list 'args', and I can't find any way to determine what the names
> were in the parent's local scope when the function was called.
> Is there any way for a function to retrieve this information?

You may have access to parent frame with something like this :
 
import sys

def show_locals(func):
    callerFrame = sys._getframe(1)
    locals = eval("locals()", callerFrame.f_globals, callerFrame.f_locals)
    print func, locals

def f():
    x = 1
    def g(y):
        w = 2
        show_locals("g")
    g(x)
    show_locals("f")

f()


If you want to write a dbgval function as you describe, you'll need
to pass variable names instead of variable references, in fact you
should pass any string that may be evaluated :

import sys

def dbgval(*names):
    callerFrame = sys._getframe(1)
    for name in names:
        val = eval(name, callerFrame.f_globals, callerFrame.f_locals)
        print "%s = %s" %(name, val)


Finally, if for some reason you don't know precisely which names you want
to investigate, but still don't want to use a debugger, you can try the
following code that allow some interactive investigation using the
simplicity of adding a single 'print' like statement :

import sys

def debug():
    try:
        import readline
    except:
        pass

    try:
        callerFrame = sys._getframe(1)
    except: # 1.5.2
        exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
        exceptionFrame = exceptionTraceback.tb_frame
        callerFrame = exceptionFrame.f_back

    while 1:
        try:
            s = raw_input("debug> ")
            exec s in callerFrame.f_globals, callerFrame.f_locals
        except EOFError:
            break
        except SystemExit:
            raise
        except:
            traceback.print_exc()

(add 'debug()' at some place, and you'll be able to issue some statements
like 'print a', or 'a.doSomething()')

Pedro




More information about the Python-list mailing list