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)]
Answer from munk on Stack Overflowpdb 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)]
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')
Videos
data breakpoints with pdb
...much like you can watch a memory address in gdb...
- GDB uses data breakpoints, this is made easy with hardware support (hardware watchpoints), this typically involves marking the memory pages read-only which then trips an exception handler on memory access. When hardware watchpoints are not available it uses software watchpoints, these are only useful in single threads and are much slower.
- PDB does not support data breakpoints, so the short answer is NO, you cannot do it with PDB out of the box.
printing variables when hitting breakpoints in pdb
For watching a variable when you are hitting a breakpoint, you can use the commands command. E.g. printing some_variable when hitting breakpoint #1 (canonical example from pdb doc).
(Pdb) commands 1
(com) print(some_variable)
(com) end
(Pdb)
Additionally, you can use the condition command to ensure the breakpoint is only hit whenever the variable takes a certain value.
eg:
(Pdb) condition 1 some_variable==some_value
other solutions
You can use tracing / profiling functions to examine things step by step using sys.settrace and checking out the opcodes being executed.
Here is some code to get you started:
import sys
import dis
def tracefn(frame, event, arg):
if event == 'call':
print("## CALL", frame)
frame.f_trace_opcodes = True
elif event == 'opcode':
opcode = frame.f_code.co_code[frame.f_lasti]
opname = dis.opname[opcode]
print("## OPCODE", opname)
return tracefn
watchme = 123
def foo():
global watchme
watchme = 122
sys.settrace(tracefn)
foo()
You will probably need to spy on all the STORE_* opcodes. https://docs.python.org/3/library/dis.html
For Python 3:
you can use display functionality of pdb
Once you hit the breakpoint just type
ipdb> display expression
example:
ipdb> display instance
display instance: <AppUser: dmitry4>
ipdb> display instance.id
display instance.id: 9
ipdb> display instance.university
display instance.university: <University: @domain.com>
ipdb> display
Currently displaying:
instance.university: <University: @domain.com>
instance.id: 9
instance: <AppUser: dmitry4>
ipdb>
as you can see, each time you type display - it will print all of your watches (expressions). You can use builtin function undisplay to remove certain watch.
You can also use pp expression to prettyprint the expression (very useful)