Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you watch a variable in pdb

Tags:

python

pdb

I'm debugging a python script, and I want to watch a variable for a change (much like you can watch a memory adress in gdb). Is there a way to do this?

like image 358
Nathaniel Flath Avatar asked Oct 05 '11 23:10

Nathaniel Flath


People also ask

How do I print a variable in pdb?

Enter p variable_name at the (Pdb) prompt to print its value.

How do you use pdb?

Starting Python Debugger 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().


2 Answers

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.

https://docs.python.org/3/library/sys.html#sys.settrace

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

like image 184
dnozay Avatar answered Sep 22 '22 04:09

dnozay


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)

like image 36
DmitrySemenov Avatar answered Sep 23 '22 04:09

DmitrySemenov