How to print all variables values when debugging Python with pdb, without specifying each variable?
Solution 1:
pdb is a fully featured python shell, so you can execute arbitrary commands.
locals()
and globals()
will display all the variables in scope with their values.
You can use dir()
if you're not interested in the values.
When you declare a variable in Python, it's put into locals or globals as appropriate, and there's no way to distinguish a variable you defined and something that's in your scope for another reason.
When you use dir(), it's likely that the variables you're interested in are at the beginning or end of that list. If you want to get the key, value pairs
Filtering locals() might look something like:
>>> x = 10
>>> y = 20
>>> {k: v for k,v in locals().iteritems() if '__' not in k and 'pdb' not in k}
{'y': 20, 'x': 10}
If your locals() is a real mess, you'll need something a little more heavy handed. You can put the following function in a module on your pythonpath and import it during your debugging session.
def debug_nice(locals_dict, keys=[]):
globals()['types'] = `__import__`('types')
exclude_keys = ['copyright', 'credits', 'False',
'True', 'None', 'Ellipsis', 'quit']
exclude_valuetypes = [types.BuiltinFunctionType,
types.BuiltinMethodType,
types.ModuleType,
types.TypeType,
types.FunctionType]
return {k: v for k,v in locals_dict.iteritems() if not
(k in keys or
k in exclude_keys or
type(v) in exclude_valuetypes) and
k[0] != '_'}
I've added an example session on pastebin
There are a couple of cases this misses. And you might want to extend it to allow you to pass in types too. But it should let you filter most everything but the variables you defined.
dir()
If you just want the last 20 values so you get output like >>> p var1 var2 ... varn
would give you, then you're better off slicing dir() like dir()[-20:], but you won't easily see the relationship between the variables and values. eg: "Did I declare foo before or after bar?"
If you want to see that relationship, you can try something like this, which assumes that your variables are at the end of dir(). You can slice differently if they're at the beginning. This won't work well if your variables aren't contiguous.
>>> zip(dir(), [eval(var) for var in dir()])[-4:]
[('a', 10), ('var', 'var'), ('x', 30), ('y', 50)]
Solution 2:
As given in this list for multiple languages:
a = 1
b = 1
n = 'value'
#dir() == ['__builtins__', '__doc__', '__name__', '__package__', 'a', 'b', 'n']
for var in dir()[4:]:
value_of_var = eval(var)
print(value_of_var)
Output:
1
1
'value'
Labelling each one is as simple as printing var + " equals " + eval(var)
.
You state your "ideal output" is exactly the result as typing p a, b, ... , n, ...
:
vars = []
for var in dir()[4:-1]
vars.append(var)
print(tuple(vars))
Output looks like:
(1, 1, 'value')