Get locals from calling namespace in Python

Question:

I want to retrieve the local variables from Python from a called function. Is there any way to do this? I realize this isn’t right for most programming, but I am basically building a debugger. For example:

def show_locals():
  # put something in here that shows local_1.

local_1 = 123
show_locals()  # I want this to show local_1.

What do I put in the body of show_locals? If I have to modify the calling statement, what is the minimal modification I can make?

Note: this must work when show_locals is in a different module to its caller.

Asked By: Peter

||

Answers:

If you’re writing a debugger, you’ll want to make heavy use of the inspect module:

def show_callers_locals():
    """Print the local variables in the caller's frame."""
    import inspect
    frame = inspect.currentframe()
    try:
        print(frame.f_back.f_locals)
    finally:
        del frame
Answered By: Gareth Rees

You use the python builtin, dir() or vars():

vars(object)

For examples using dir(), see: this post

Examples using vars:

>>> class X:
...     a=1
...     def __init__(self):
...         b=2
... 
>>> 
>>> vars(X)
{'a': 1, '__module__': '__main__', '__doc__': None, '__init__': <function __init__ at 0x100488848>}
>>> 
>>> vars(X())
{}

A potentially problematic fact: New style classes not return the same result

>>> class X(object):
...     a=1
...     def __init__(self):
...         b=2
... 
>>> 
>>> vars(X)
<dictproxy object at 0x1004a1910>
>>> vars(X())
{}

Also: for an instantiated class (new and old style), if you add a variable after instantiating, vars will return the object’s dict like this:

>>> x = X() 
>>> x.c = 1
>>> vars(x)
{'c': 1}
>>> 

See: http://docs.python.org/library/functions.html#vars

Answered By: Alex Gaudio

Perhaps it is worth pointing out that the technique from the accepted answer that reads from the caller’s stack frame:

import inspect
def read_from_caller(varname):
    frame = inspect.currentframe().f_back
    try:
        v = frame.f_locals[varname]
        return v
    finally:
        del frame

can also write into the caller’s namespace:

import inspect
def write_in_caller(varname, v):
    frame = inspect.currentframe().f_back
    try:
        frame.f_locals[varname] = v
    finally:
        del frame

If you put that in a module called "access_caller", then

import access_caller
access_caller.write_in_caller('y', x)

is an elaborate way of writing

y = x

(I am writing this as a fresh answer because I don’t have enough reputation points to write a comment.)

Answered By: Daniel Wagenaar
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.