39

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.

denis
  • 21,378
  • 10
  • 65
  • 88
Amelio Vazquez-Reina
  • 91,494
  • 132
  • 359
  • 564
  • Out of curiosity, why would you ever want more than one tracer at once? At that point it seems like you should be doing logging, not debugging. – Wilduck Jan 31 '13 at 21:28
  • @Wilduck: I would like to inspect my workspace under certain circumstances, and those circumstances may occur in different locations in my code. – Amelio Vazquez-Reina Jan 31 '13 at 21:30
  • Okay, maybe I phrased my question poorly. I understand why you would want to look at different parts of your code. Why would you want to have those tracers in your code _at the same time_? If you're not using the debugger to permanently fix a bug (i.e. one bug at a time) wouldn't it be better/easier to set up logging to automatically collect information about how your program is running in various states? I'm asking because it seems that you're trying to use debugging tools for something logging takes care of. – Wilduck Jan 31 '13 at 21:38
  • 1
    Thanks @Wilduck. I am not really interested in logging. I would like to mathematically and interactively examine the value of several variables when certain conditions are met. I could certainly dump the variables to disk and inspect them later, but that would not allow me to resume execution, which sometimes I want. This type of workflow is common and powerful in scientific computing (e.g. MATLAB supports this through the use of `keyboard` statements) and it allows one to inspect and visualize data interactively without fully disrupting or having to reinitialize a program. – Amelio Vazquez-Reina Jan 31 '13 at 21:44
  • 1
    I see, that does make sense. I'll leave my answer up, since it might be useful to someone stumbling on this question later, but I'm afraid I don't have any further suggestions for you personally. Good luck. – Wilduck Jan 31 '13 at 21:50

8 Answers8

37

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
pankaj
  • 1,450
  • 14
  • 15
  • 1
    @Arnon how to use `set_trace()`; which `set_trace`? Plain old `ipdb.set_trace()` produces [this problem for me](https://stackoverflow.com/q/35613249/1175496), which advises to use `Tracer()()`! Oh, maybe the `Pdb.set_trace()` seen [here](https://ipython.org/ipython-doc/rel-0.13.1/api/generated/IPython.core.debugger.html#IPython.core.debugger.Pdb.set_trace) or [here](https://stackoverflow.com/a/1127087/1175496) ; the [documentation linked](http://ipython.readthedocs.io/en/stable/api/generated/IPython.core.debugger.html) describes `IPython.core.debugger.set_trace`, but I don't have that func. – Nate Anderson Jun 05 '17 at 15:44
  • The documentation linked is for IPython 6 (which only supports Python 3), and my suspicion is that you are using an older version. `IPython.core.debugger.Tracer` still exists and works in IPython 6, even if deprecated. I guess you can continue using it for some time until it is actually removed from the codebase. – pankaj Jun 06 '17 at 17:34
  • Haha, that's true, I'm using `Tracer` nonetheless, hopefully someone can describe the recommended alternative? – Nate Anderson Jun 06 '17 at 18:07
  • Man, I wish IPython would stop moving the goalposts every couple of years – jez Jul 19 '22 at 03:29
  • This answer is broken for the current version of python. – James Dalgleish Aug 20 '23 at 18:17
21

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.

Wilduck
  • 13,822
  • 10
  • 58
  • 90
13

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
Medhat Omr
  • 518
  • 5
  • 9
  • I wanted to add this answer as a comment to the accepted answer above, but I don't have enough reputation to comment, so I hope if this answer helps anyone – Medhat Omr Aug 10 '17 at 16:21
  • 1
    Alternatively, you can directly use `IPython.core.debugger.set_trace()` without needing `Pdb`. – Keith Prussing Oct 13 '17 at 13:29
12

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().

Niko Föhr
  • 28,336
  • 10
  • 93
  • 96
Donal
  • 8,430
  • 3
  • 16
  • 21
9

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.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • 1
    Thanks, but it's not clear how the first solution would allow me to specify **possible locations of my choice for breakpoints**. As for the second one, how would I actually use that option? Finally, from what I understand, `pdb` does not offer the same features that IPython does for introspection, etc. Is that correct? – Amelio Vazquez-Reina Jan 31 '13 at 21:29
  • You can use the `b` pdb command to define the breakpoints once you run the debugger. – Kos Jun 30 '15 at 07:12
5

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.

dvreed77
  • 2,217
  • 2
  • 27
  • 42
0

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:\users\c81196\lgd\mortgages-1\nmb\lgd\run_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.

vaudt
  • 151
  • 6
0

if you are using pytest then

pip install ipython
pip install ipdb
# run tests with options
pytest --pdb --pdbcls=IPython.terminal.debugger:TerminalPdb

# or set it in pytest.ini
[pytest]
addopts = --pdbcls=IPython.terminal.debugger:TerminalPdb

Javed
  • 5,904
  • 4
  • 46
  • 71