Many people use the standard Python debugger (pdb or ipdb) because it works
well and can be used as a standalone tool or with your favorite editor. I’ve used it for
years, but today I’m more productive using the PyCharm debugger. It can debug Python,
JavaScript, and Django and Jinja Templates (making the debugging process seamless in web
applications). Also, I don’t have to worry about leaving pdb.set_trace
calls around
anymore.
Since the process to run and debug code in PyCharm is similar, we will look how to run code first (jump to the debugging section if you already know how to run code in PyCharm).
In this article shortcuts are written with the first letter of keyboard modifiers followed by the actual keys in lower case. The keys are presented for both OS X and Windows/Linux in the format (mac, win). For example, the shortcut (⌘-S-⌥-t, S-A-C-t) means to press the keys ⌘, Shift, Option, and t at the same time on the Mac, and Shift, Alt, Control, and t on Windows and Linux. When only one shortcut is presented, it will be the same on all operating systems.
Running Python Code
If we haven’t run any code in our project before, the icons to run and debug will be disabled:
Some items will be disabled in the Run menu as well:
To run a script for the first time, we need to either create a configuration (Run→Edit
Configurations…) or ask PyCharm to run the current file by going to
Run→Run… (⌥-C-r, A-C-r), where PyCharm will automatically offer to run the
current file. In the following example I’m editing a file named analysis.py
. Notice how
PyCharm creates a new configuration named analysis
:
PyCharm will run the file and show a tool window with the results, if any.
The Run tool window has many buttons to help us deal with the running script. We can do things like pause, stop, and rerun the script and move up and down the stack trace.
The following table summarizes the main actions. The manual has a complete description.
Name | Shortcut | Description |
---|---|---|
Rerun | `(⌘-r, C-F5)` | Stop the current process and run it again |
Stop | `(⌘-F2, C-F2)` | Stop the current process |
Pause Output | Keep running the process but don’t show its output | |
Restore Layout | Restore the default window layout, discarding the current one | |
Pin Tab | Run code on a new tab | |
Close | `(⌘-w, S-C-F4)` | Closes the current tab and terminate the process |
Up the stack trace | `(⌘-⌥-↑, A-C-↑)` | Navigate up the stack trace |
Down the stack trace | `(⌘-⌥-↓, A-C-↓)` | Navigate down the stack trace |
Use Soft Wraps | Enable word wrap for long lines | |
Clear All | Remove all text in the console |
We can hide the Run tool window with (⌘-4, A-4).
Once a script is run for the first time, it becomes available in the Run
menu. PyCharm
will show the most recently run command in Run→Run '<script name>' (C-r, S-F10)
, where
<script name>
is the name of the Python file without the extension (analysis
, in our
previous example).
This command will run the original file even if we are working on a different one. In our
example, if we are editing a different file (say chorales.py
) and type C-r
on the Mac
or S-F10
on Windows or Linux, PyCharm will run the file analysis.py
, since this is
the last file we ran. This is useful when we have a master script and are making
modifications to a sub-module, for instance.
After we run the script for the first time, the related commands in the menubar will be available, and we can choose the script to run there:
PyCharm will create a new tab every time we run a script. If we don’t close the previous tab we may end up with many different tabs, so make sure you close each tab after running, and are, in fact, on the right tab.
New Configuration
When we want to run things with more control we need to create a configuration by going to Run→Edit Configurations… and clicking on the + button (⌘-n, A-Insert). PyCharm will ask what type of configuration we want (that is, if we want to run a Python script, a Django or Pyramid server, and so on) and will show the appropriate options for each type.
We can choose the script to run, passing parameters if necessary, the Python interpreter, and the working directory. We can also launch an external tool before running the script, which is great if we need to do things like data pre-processing.
In the Logs tab we can add log files to be shown in PyCharm’s console during the script execution or save the console output to a file.
Naturally, we can have multiple configurations; we can switch between them by going to Run→Run… (⌥-C-r, A-C-r) and picking the one we want.
The Python Debugger
To debug code in PyCharm, we need to create a new configuration in Run→Edit
Configurations… or debug an existing script by going to Run→Debug…
(⌥-C-d, S-A-F9). After that it will be available in
Run→Debug '<script name>' (C-d, S-F9)
, where <script name>
is the name of the Python
file without the extension (analysis
, in our example). As you can see, it works just
like running code.
Similarly to the Run
command, the menubar will now be enabled and we can choose the
script to debug by clicking on the insect icon.
One of the main differences between running and debugging a script is that in debugging we want to define breakpoints. In PyCharm, a breakpoint must be on a line with working code; it can’t be on a line that is blank or starts with a comment. We create breakpoints by clicking on the gutter on the left.
We can also create a temporary breakpoint by Alt-clicking on the gutter. As the name suggests, a temporary breakpoint will be removed after being hit. Notice that the temporary breakpoint icon is different from the regular one. Check the manual for more information about breakpoint icons.
PyCharm’s debug tool window has everything we expect in a graphical debugger. From here we can navigate the call stack and inspect the data available in each stack frame. We can keep an eye on some variables by adding them to the watch list.
The debug tool window has many of the buttons we have seen in the Run tool window, allowing us to pause, stop, and rerun the script. In addition, we can view the breakpoints—also available in Run→View Breakpoints… (⌘-S-F8, S-C-F8)—and mute (that is, disable) all breakpoints.
The icons in the top right corner, allowing us to step in and out of the program, are the ones we will use the most:
In the following image, we can see each icon with its name. The table below shows the name, shortcut, and description for each icon.
Name | Shortcut | Description |
---|---|---|
Show Execution Point | `(⌥-F10, A-F10)` | Go back to the execution point. Useful if we visit other files and want to go back |
Step Over | `(F8)` | Step to the next line |
Step Into | `(F7)` | Descend into a method or function call on the next line |
Force Step Into | `(S-⌥-F7, S-A-F7)` | Descend into the method even if it’s to be skipped |
Step Out | `(S-F8)` | Return to the line where the current function was called |
Run to Cursor | `(⌥-F9, A-F9)` | Run the code where the caret is located. Useful to skip stepping over uninteresting code |
Evaluate Expression | `(⌥-F8, A-F8)` | Evaluate an expression or code fragment |
The variables pane is a great way to explore complex data. It was invaluable when I was
learning Django and getting acquainted with the HttpRequest
object, for instance. In
the following example, we can see some music21 data, especially the complex Score
class. The Variables pane helps me to inspect attributes such as duration
and
elements
.
We can see all breakpoints in Run→View Breakpoints… (⌘-S-F8, S-C-F8). From here we can add, remove, or edit breakpoints; and set conditional breakpoints and log messages or expressions.
One way to quickly edit a breakpoint is to right-click on the breakpoint on the gutter. A popup will allow us to enable the breakpoint and add a condition.
We can also see the breakpoints by selecting the Favorites Tool (⌘-2, A-2).
A quick way to disable a breakpoint is by clicking on it with the Alt key. The breakpoint icon will change.
Another way to disable a breakpoint is by right-clicking on it and unchecking the first option (“Line 93 in analysis.py enabled” in the following example).
Besides defining breakpoints when a line of code is reached, we can define a breakpoint that is triggered when an exception is thrown. To add an exception breakpoint, we go to Run→View Breakpoints… (⌘-S-F8, S-C-F8) and select Python Exception Breakpoint after clicking the + button.
We need to include the exception class by searching for its name. The search field works with both built-in and custom exception classes.
Our new exception now appears on the list, where we can customize it.
In most cases, we want to activate the breakpoint when the exception is raised (the default is to activate the breakpoint when the exception terminates):
Having configured an exception breakpoint, PyCharm will create the breakpoint
automatically when the exception is raised (ChoralException
, in our example). Notice
that the exception breakpoint icon is different from the regular one.
Python Prompt
Sometimes it’s useful to be able to access a Python prompt while debugging. We can do this by clicking on the Console tab when the debugger is running and selecting the Show Python Prompt icon.
Now we can use the prompt to inspect and change the variables in the current scope.
Evaluating Expressions
Although it’s super-useful to have a full Python prompt available while debugging, the Evaluate Expression feature may be sufficient if we just want to quickly evaluate an expression.
As expected, we can use any variable in the current scope:
If we select the Code Fragment Mode button, we can add multiple lines of code. Completion works here as usual.
Inspecting and Watching Variables
The fastest way to inspect the value of variables while debugging is by hovering the cursor over a variable name. PyCharm will show the variable name and its value.
And, as expected, we can inspect and set a variable value by choosing the correct option in the popup menu on the Variables pane.
The same apply to watched variables; we can edit and inspect them by using the popup menu.
Remote Debugging
PyCharm has support to debug code remotely. Probably, the most popular and useful way is to debug code in a Vagrant box.
Conclusion
PyCharm has a debugger that is second to none. If you want to learn more about PyCharm and how to use it to debug JavaScript and Django templates, check my ebook, Modern Python Development with PyCharm.