Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to print all variables values when debugging Python with pdb, without specifying each variable?

I'm debugging my Python scripts using pdb and the manual says I can use p variables command to print the values of the specified variables at a certain point. But what if I had lots of variables, like 20 variables, and I would like to track the value of all of them? How do I print all of them without specifying each one manually? Take for example this script:

a = 1 b = 2 c = 3 

I can debug it with pdb and print all of them using p a, b, c like this:

$ python -m pdb test.py  > /media/test.py(1)<module>() -> a = 1 (Pdb) n > /media/test.py(2)<module>() -> b = 2 (Pdb) n > /media/test.py(3)<module>() (Pdb) n --Return-- > /media/test.py(3)<module>()->None -> c = 3 (Pdb) p a, b, c (1, 2, 3) (Pdb)  

But I have to manually specify each variable. Is there a way of print all variables at once, without specifying each one of them?

like image 218
renatov Avatar asked Feb 22 '14 22:02

renatov


People also ask

How do I debug Python code using pdb?

To start debugging within the program just insert import pdb, pdb. set_trace() commands. Run your script normally, and execution will stop where we have introduced a breakpoint. So basically we are hard coding a breakpoint on a line below where we call set_trace().


1 Answers

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)] 
like image 65
munk Avatar answered Oct 04 '22 04:10

munk