Breakpoint-induced interactive debugging of Python with IPython
Question:
Say I have an IPython session, from which I call some script:
> run my_script.py
Is there a way to induce a breakpoint in my_script.py
from which I can inspect my workspace from IPython?
I remember reading that in previous versions of IPython one could do:
from IPython.Debugger import Tracer;
def my_function():
x = 5
Tracer()
print 5;
but the submodule Debugger
does not seem to be available anymore.
Assuming that I have an IPython session open already: how can I stop my program a location of my choice and inspect my workspace with IPython?
In general, I would prefer solutions that do not require me to pre-specify line numbers, since I would like to possibly have more than one such call to Tracer()
above and not have to keep track of the line numbers where they are.
Answers:
Inside the IPython shell, you can do
from IPython.core.debugger import Pdb
pdb = Pdb()
pdb.runcall(my_function)
for example, or do the normal pdb.set_trace()
inside your function.
You can run it and set a breakpoint at a given line with:
run -d -b12 myscript
Where -b12 sets a breakpoint at line 12. When you enter this line, you’ll immediately drop into pdb, and you’ll need to enter c
to execute up to that breakpoint.
I have always had the same question and the best workaround I have found which is pretty hackey is to add a line that will break my code, like so:
...
a = 1+2
STOP
...
Then when I run that code it will break, and I can do %debug to go there and inspect. You can also turn on %pdb to always go to point where your code breaks but this can be bothersome if you don’t want to inspect everywhere and everytime your code breaks. I would love a more elegant solution.
The Tracer()
still exists in ipython in a different module. You can do the following:
from IPython.core.debugger import Tracer
def my_function():
x = 5
Tracer()()
print 5
Note the additional call parentheses around Tracer
edit: For IPython 6 onwards Tracer
is deprecated so you should use set_trace()
instead:
from IPython.core.debugger import set_trace
def my_function():
x = 5
set_trace()
print 5
This is the version using the set_trace()
method instead of the deprecated Tracer()
one.
from IPython.core.debugger import Pdb
def my_function():
x = 5
Pdb().set_trace()
print 5
With Python 3 (v3.7+), there’s the new breakpoint()
function. You can modify it’s behaviour so it’ll call ipython’s debugger for you.
Basically you can set an environment variable that points to a debugger function. (If you don’t set the variable, breakpoint()
defaults to calling pdb.)
To set breakpoint()
to call ipython’s debugger, set the environment variable (in your shell) like so:
# for bash/zsh users
export PYTHONBREAKPOINT='IPython.core.debugger.set_trace'
# powershell users
$env:PYTHONBREAKPOINT='IPython.core.debugger.set_trace'
(Note, obviously if you want to permanently set the environment variable, you’ll need to modify your shell profile or system preferences.)
You can write:
def my_function():
x = 5
breakpoint()
print 5;
And it’ll break into ipython’s debugger for you. I think it’s handier than having to import from IPython.core.debugger import set_trace
and call set_trace()
.
I see a lot of options here, but maybe not the following simple option.
Fire up ipython in the directory where my_script.py
is.
Turn the debugger on if you want the code to go into debug mode when it fails. Type %pdb
.
In [1]: %pdb
Automatic pdb calling has been turned ON
Next type
In [2]: %run -d ./my_script.py
*** Blank or comment
*** Blank or comment
NOTE: Enter 'c' at the ipdb> prompt to continue execution.
> c:usersc81196lgdmortgages-1nmblgdrun_lgd.py(2)<module>()
1 # system imports
----> 2 from os.path import join
Now you can set a breakpoint where ever you want it.
Type b 100
to have a breakpoint at line 100, or b whatever.py:102
to have a breakpoint at line 102 in whatever.py
.
For instance:
ipdb> b 100
Then continue to run, or continue.
ipdb> c
Once the code fails, or reaches the breakpoint you can start using the full power of the python debugger pdb
.
Note that pdb
also allows the setting of a breakpoint at a function.
b(reak) [([filename:]lineno | function) [, condition]]
So you do not necessarily need to use line numbers.
Say I have an IPython session, from which I call some script:
> run my_script.py
Is there a way to induce a breakpoint in my_script.py
from which I can inspect my workspace from IPython?
I remember reading that in previous versions of IPython one could do:
from IPython.Debugger import Tracer;
def my_function():
x = 5
Tracer()
print 5;
but the submodule Debugger
does not seem to be available anymore.
Assuming that I have an IPython session open already: how can I stop my program a location of my choice and inspect my workspace with IPython?
In general, I would prefer solutions that do not require me to pre-specify line numbers, since I would like to possibly have more than one such call to Tracer()
above and not have to keep track of the line numbers where they are.
Inside the IPython shell, you can do
from IPython.core.debugger import Pdb
pdb = Pdb()
pdb.runcall(my_function)
for example, or do the normal pdb.set_trace()
inside your function.
You can run it and set a breakpoint at a given line with:
run -d -b12 myscript
Where -b12 sets a breakpoint at line 12. When you enter this line, you’ll immediately drop into pdb, and you’ll need to enter c
to execute up to that breakpoint.
I have always had the same question and the best workaround I have found which is pretty hackey is to add a line that will break my code, like so:
...
a = 1+2
STOP
...
Then when I run that code it will break, and I can do %debug to go there and inspect. You can also turn on %pdb to always go to point where your code breaks but this can be bothersome if you don’t want to inspect everywhere and everytime your code breaks. I would love a more elegant solution.
The Tracer()
still exists in ipython in a different module. You can do the following:
from IPython.core.debugger import Tracer
def my_function():
x = 5
Tracer()()
print 5
Note the additional call parentheses around Tracer
edit: For IPython 6 onwards Tracer
is deprecated so you should use set_trace()
instead:
from IPython.core.debugger import set_trace
def my_function():
x = 5
set_trace()
print 5
This is the version using the set_trace()
method instead of the deprecated Tracer()
one.
from IPython.core.debugger import Pdb
def my_function():
x = 5
Pdb().set_trace()
print 5
With Python 3 (v3.7+), there’s the new breakpoint()
function. You can modify it’s behaviour so it’ll call ipython’s debugger for you.
Basically you can set an environment variable that points to a debugger function. (If you don’t set the variable, breakpoint()
defaults to calling pdb.)
To set breakpoint()
to call ipython’s debugger, set the environment variable (in your shell) like so:
# for bash/zsh users
export PYTHONBREAKPOINT='IPython.core.debugger.set_trace'
# powershell users
$env:PYTHONBREAKPOINT='IPython.core.debugger.set_trace'
(Note, obviously if you want to permanently set the environment variable, you’ll need to modify your shell profile or system preferences.)
You can write:
def my_function():
x = 5
breakpoint()
print 5;
And it’ll break into ipython’s debugger for you. I think it’s handier than having to import from IPython.core.debugger import set_trace
and call set_trace()
.
I see a lot of options here, but maybe not the following simple option.
Fire up ipython in the directory where my_script.py
is.
Turn the debugger on if you want the code to go into debug mode when it fails. Type %pdb
.
In [1]: %pdb
Automatic pdb calling has been turned ON
Next type
In [2]: %run -d ./my_script.py
*** Blank or comment
*** Blank or comment
NOTE: Enter 'c' at the ipdb> prompt to continue execution.
> c:usersc81196lgdmortgages-1nmblgdrun_lgd.py(2)<module>()
1 # system imports
----> 2 from os.path import join
Now you can set a breakpoint where ever you want it.
Type b 100
to have a breakpoint at line 100, or b whatever.py:102
to have a breakpoint at line 102 in whatever.py
.
For instance:
ipdb> b 100
Then continue to run, or continue.
ipdb> c
Once the code fails, or reaches the breakpoint you can start using the full power of the python debugger pdb
.
Note that pdb
also allows the setting of a breakpoint at a function.
b(reak) [([filename:]lineno | function) [, condition]]
So you do not necessarily need to use line numbers.