146

Just a convenience question. I've been a bit spoiled with debuggers in IDEs like Visual Studio and XCode. I find it a bit clumsy to have to type import pdb; pdb.set_trace() to set a breakpoint (I'd rather not import pdb at the top of the file as I might forget and leave it in).

Is there a simpler way of setting a breakpoint in Python code, as straightforward and unobtrusive as what you see in an IDE?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Joe
  • 46,419
  • 33
  • 155
  • 245
  • Use PyCharm. How could it be simpler than entering a breakpoint line, except for running using a Python IDE? – Ciro Santilli OurBigBook.com Aug 31 '18 at 07:26
  • Just use `python -m pdb .py` then `b ` to set the breakpoint at chosen line number (no function parentheses). Hit `c` to continue to your breakpoint. You can see all your breakpoints using `b` command by itself. Type `help` to see other pdb commands available whilst debugging. – arcseldon Feb 18 '19 at 06:12
  • 7
    Since Python 3.7, you can now use the builtin `breakpoint()` function. https://www.python.org/dev/peps/pep-0553/ – Daniel Jul 10 '19 at 09:33

15 Answers15

148

You can run your program into pdb from the command line by running

python -m pdb your_script.py

It will break on the 1st line, then you'll be able to add a breakpoint wherever you want in your code using the break command, its syntax is:

b(reak) [[filename:]lineno | function[, condition]]

It is flexible enough to give you the ability to add a breakpoint anywhere.

sashoalm
  • 75,001
  • 122
  • 434
  • 781
mdeous
  • 17,513
  • 7
  • 56
  • 60
  • 31
    to clarify this point, if I `pdb.set_trace()` and go into the debugger, use the `l` command (list) and see that I want to set a breakpoint at line 27, I would then enter: `b 27` and the debugger would set a breakpoint at line 27 (I found the documentation a little challenging to understand, so wanted to add that point of clarification). – benjaminmgross Aug 06 '13 at 16:01
  • 12
    Also, if you have an object `x`, and you want to stop when its method `f` is called, you can say `break x.f`, and then `c(ontinue)`. This works even if the object is in an inaccessible file or was created dynamically, e.g. by unpickling. – Sergey Orshanskiy Oct 18 '14 at 15:56
  • 4
    When debugging after a stacktrace you can copy the fullpath to a module and append the line number like `b /data/users/me/project/env/local/lib/python2.7/site-packages/django/core/urlresolvers.py:596` – valid Aug 07 '18 at 06:53
  • what if you don't have access to the code though? Imagine you installed a third party app, it's crashing, and you need to know why. How to use pdb then? – Adrian Nov 18 '21 at 18:23
  • Using `b lineno` in debugger I receive: *"AttributeError: type object 'Breakpoint' has no attribute '__next__'"*, referring to **"File "G:\Python3\python~1.7\lib\bdb.py", line 489, in __init__ self.number = Breakpoint.__next__ "**. It happens with any valid line number. Any idea how to solve this? – Apostolos Apr 19 '22 at 09:56
69

You can use:

from pdb import set_trace as bp

code
code
bp()
code
code
Apogentus
  • 6,371
  • 6
  • 32
  • 33
  • 1
    not sure why the superflous aliasing, but ;-). For some reason my IDE/Editor (vscode) was being a mare this AM and keeps underlining. Seeing your comment really helped me. Have a great day! – MrMesees Nov 13 '18 at 08:09
  • 1
    How can I force to import `set_trace` only when I do use bp()? – alper Jul 06 '20 at 01:02
48

I haven't tried it yet but they just implemented a new built-in called breakpoint() in Python 3.7 which means you can insert a breakpoint with one statement now:

breakpoint()
Bill
  • 10,323
  • 10
  • 62
  • 85
44

In vim, I have a macro set up for this (in my .vimrc file):

map <silent> <leader>b oimport pdb; pdb.set_trace()<esc>
map <silent> <leader>B Oimport pdb; pdb.set_trace()<esc>

so I can just press \b (when not in Insert Mode) and it adds in a breakpoint after the current line, or \B (note the capital) and it puts one before the current line.

which seems to work alright. Most other 'simple' programmers editors (emacs, sublimetext, etc) should have similar easy ways to do this.

Edit: I actually have:

au FileType python map <silent> <leader>b oimport pdb; pdb.set_trace()<esc>
au FileType python map <silent> <leader>B Oimport pdb; pdb.set_trace()<esc>

which turns it on only for python source files. You could very easily add similar lines for javascript or whatever other languages you use.

2019 Update (Python 3.7+)**

Python 3.7+ now has the builtin breakpoint() which can replace the previous import pdb; pdb.set_trace() in vim. It still works the same.

2021 Update

So I'm doing a lot of django these days, I'm using the ipdb debugger also, with some javascript and some HTML templating, so now have:

function InsertDebug()
    if &filetype == "python"
        execute "normal! oimport ipdb;ipdb.set_trace()\<esc>"
    elseif &filetype == "javascript"
        execute "normal! odebugger;\<esc>"
    elseif &filetype == "html" || &filetype == "htmldjango"
        execute "normal! o{% load debugger_tags %}{{ page\|ipdb }}\<esc>4bcw"
    else
        echoerr "Unknown filetype - cannot insert breakpoint"
    endif
endfunction
nmap <leader>b <esc>:call InsertDebug()<CR>

so I get either the ipdb breakpoint, or other language breakpoints in those languages. Then this is easily extendible to other languages too. I think it would be possible to use better autocommands to do this - but I couldn't get it to work as reliably as this.

Daniel
  • 1,410
  • 12
  • 17
  • 2
    Nice solution, and the added line will have the correct indentation too if you have `set autoindent` in your *.vimrc* file. – Jealie Apr 01 '14 at 00:52
  • Yes, I can't understand why most distros don't ship with `set autoindent` (and a bunch of other options) as standard. One of the first things I do with a new system is pull in a better vimrc... – Daniel Aug 06 '14 at 16:19
  • 1
    Just use a vim named register! Save the line that you want to buffer 'd' (as in **d**ebug) by pressing `"dyy` and whenever you need it just do `"dp` or `"dP`. Learn [vim registers](http://usevim.com/2012/04/13/registers/)! They are very usefull and are always supported! – polvoazul Nov 10 '14 at 14:44
  • how to add :w after that? – ji-ruh Jun 23 '18 at 01:12
  • Taking the named register concept a little further, you can record a macro, perform the necessary operations and then stop the macro. Then paste the macro contents into your vimrc file. For example, start macro with `qd`, then later `"dp` to paste. Finally assign your instructions to a register so always populated on vim loadup. Example: `let @d = 'oimport pdb; pdb.set_trace()k0:w'` Now, just use `@d` whenever you want to paste the line into a file. The above also saves the file. But you'll have to record your own (rather than copy/paste above) as special chars are involved (for escape etc). – arcseldon Feb 18 '19 at 06:54
40

If you don't want to manually set breakpoints every time running the program (in Python 3.2+), e.g. say you want to directly create a breakpoint at line 3 and stop the execution there:

python -m pdb -c "b 3" -c c your_script.py

The following information may help:

If a file .pdbrc exists in the user’s home directory or in the current directory, it is read in and executed as if it had been typed at the debugger prompt. This is particularly useful for aliases. If both files exist, the one in the home directory is read first and aliases defined there can be overridden by the local file.

Changed in version 3.2: .pdbrc can now contain commands that continue debugging, such as continue or next. Previously, these commands had no effect.

New in version 3.2: pdb.py now accepts a -c option that executes commands as if given in a .pdbrc file, see Debugger Commands.

Community
  • 1
  • 1
AXO
  • 8,198
  • 6
  • 62
  • 63
  • @Friedrich Since January 1st, 2020, Python 2 is no longer supported. There may be some backports that you can install, however, if you're going to install a 3rd party lib, I'd suggest [pudb](https://github.com/inducer/pudb) (Versions 2019.2 or older for Python 2). – AXO Mar 16 '21 at 05:03
  • 2
    This is great; thank you. Just a note for future googlers: the full syntax is `b(reak) [([filename:]lineno | function) [, condition]]`, so you can break in any library code, optionally setting a condition on the breakpoint which will be evaluated in the context of the line: `python -m pdb -c "b /path/to/some_file.py:3, somevariable=26" -c c your_script.py` – Lucas Wiman Apr 12 '22 at 17:50
  • 1
    Thanks @AXO! I prefer this method as it means I do not forget `import pdb` and `set_trace` statements in my code – KolaB Oct 18 '22 at 10:39
14

This is how you would use pdb in the command line without implementing anything in your source code (the documentation and other online resources don't do a good job explaining this to a programmer who has only used visual debuggers in the past):

Start pdb by typing the following in a shell prompt:

python -m pdb 'python_script'

This command initializes pdb and the pdb debugger will break at the first line of your python_script and wait for an input from you:

(Pdb)

This is the interface for communicating with the debugger. Now, you can specify your commands here. Opposed to using buttons or keyboard shortcuts in visual debuggers, here you will use commands to derive the same results.

You can go to the next line in your code by command "n" (next):

(Pdb) n

Performing a next would display the line number, and the specific code in the source:

> python_script(line number)method name
-> current line in the source code

You can set a breakpoint by specifying a line number in your source code.

(Pdb) b 50

Here, the debugger is set to break at line 50. If there aren't any other breakpoints, the breakpoint at line 50 will be the first and it could be referenced by the breakpoint id which is 1 in this case. If you add more break points they will get identifiers sequentially (i.e., 2, 3 etc.)

Once a breakpoint is set, you would continue executing your program until pdb gets to the breakpoint as follows:

(Pdb) c

Once you get to a breakpoint you could go to the next line, with the n command as described before. If you want to examine the values of variables, you would execute the parameter command as follows:

(Pdb) p variable_name

If you no longer need a breakpoint, you can clear it by passing in the id of the breakpoint with the clear command:

(Pdb) clear 1

Finally, when you are done with the debugger you can exit the execution as you would exit the python command line interpreter.

(Pdb) exit()

I hope this will help anybody get started with pdb. Here is a list of commands you can use with the debugger: pdb so question and answers

picmate 涅
  • 3,951
  • 5
  • 43
  • 52
13

Python 3.7 has a new builtin way of setting breakpoints. Calling

breakpoint()

More here https://stackoverflow.com/a/53263117/6488361

Kaka Ruto
  • 4,581
  • 1
  • 31
  • 39
4

You could use an IDE which supports python debugging, or you can check out the excellent Winpdb tool. Which works on any platform and provides graphical debugging facilities to your python script.

http://winpdb.org/

Glenjamin
  • 7,150
  • 6
  • 25
  • 26
2

You can use:

  • wing ide
  • eclipse with the pydev plugin
  • pycharms

All of the above support python debugging from inside an IDE.

vvatsa
  • 54
  • 3
2

(I'd rather not import pdb at the top of the file as I might forget and leave it in).

Unlike

import pdb; pdb.set_trace()

which could leave the import part behind, this is "atomic":

__import__('pdb').set_trace()
mh001
  • 51
  • 2
1

Easiest way to keep breakpoints, aliases and other settings saved across run is by using .pdbrc in the same folder as your script and then just run your script as python -m pdb <scriptname>.py

Enter commands just as you would do in pdb one per line. E.g.:

.\.pdbrc
--------
b 12
display var
c
Canute S
  • 334
  • 1
  • 5
  • 12
0

In Atom if Python plugins installed, you can just type in 'pdb' and hit enter and the snippet will type import and trace back for you.

I've used to this now that sometimes I just type it in even if I'm editing it in vim and waiting for the dropdown to appear.

Simplex
  • 1
  • 1
0

You could use Vim with the Python-Mode plugin or Emacs with the Elpy plugin.

These plugins give you breakpoints with easy keystrokes (\ b in Vim and C-c C-u b in Emacs) plus many other features from heavy-weight IDEs (code folding, refactoring, linting, etc.) - all within a light-weight terminal-based text editor.

abrac
  • 521
  • 5
  • 12
0

With this snippet breakpoints can be set automatically:

import pdb
import sys
try:
    from io import StringIO           # Python3
except:
    from StringIO import StringIO     # Python2

bp = 14    # or e.g. "submodule.py:123"

sys.stdin = StringIO('break %s\ncont\n' % bp)
pdb.set_trace()
sys.stdin = sys.__stdin__   # reset to usually stdin

print(1)     # lineno 14
print(2)

This approach works with Python 2 and 3.

Breakpoints could be also set via a .pdbrc file (locally or in home) and manipulated on the fly. Still, the cont command must not executed manually. So since pdb.set_trace requires stdin, the above code just "redirects" the command to stdin in a programmatic way.

Putting the code inside the main program and combined with argparse, the breakpoints can be passed from the command line with further stop until the breakpoint.

-1

The simplest way to run the debugger on your script is just

pdb your_script.py

Running pdb on a Linux command-line gives

usage: pdb.py scriptfile [arg] ...
timbo
  • 13,244
  • 8
  • 51
  • 71