How do I list the current line in python PDB? - python

In the perl debugger, if you repeatedly list segments of code taking you away from the current line, you can return to the current line by entering the command . (dot).
I have not been able to find anything comparable using the python PDB module. If I list myself away from the current line and want to view it again, it seems I have to either remember the line number that was currently executing (unlikely for me) or execute a statement (often undesirable).
Am I missing something?

Late but hopefully still helpful. Make the following alias:
alias ll u;;d;;l
Then whenever you type ll, pdb will list from the current position. It works by going up the stack and then down the stack, which resets 'l' to show from the current position. (This won't work if you are at the top of the stack trace.)
Tip: Permanent alias
To make the alias permanent, add the line into your .pdbrc-file in the user home directory (~/.pdbrc). This works with both pdb and ipdb.

In Python 3.2 and higher, you can use list . to reset the list location.
Source: Python Bug tracker #4179

This question is 7 years old now..
If there’s anyone who are curious about this problem, just use the dot
(pdb) l .
This now works.

Well, I don't think there's a command similar to . in perl debugger, but you can always find the current line using the where / w command. That will show you both the current (contextual) frame as well as the most recent frame, which I believe is where the debugger was triggered.

Related

How do I call a function in vs code using python?

I'll want to know how to call a function in vs code. I read the answer to similar questions, but they don't work:
def userInput(n):
return n*n
userInput(5)
And appends nothing
def Input(n):
return n*n
And in the terminal:
from file import *
from: can't read /var/mail/file
Can somebody help me?
You are doing everything correctly in the first picture. In order to call a function in python on vs code you first have to define the function, which you did by typing def userInput(n):. If you want to see the result of your function, you should not use return, you should use print instead. Return is a keyword- so when your computer reaches the return keyword it attempts to send that value from one point in your code to another. If you want to see the result of your code, typing print (n) would work better.
Your code should look like this:
def userInput(n):
print (n * n)
userInput(5)
The code would print the result 25
Your terminal is your general way to access your operating system, so you have to tell it that you want it to interpret your Python code first.
If you want to run the file you're typing in, you have to first know the location of that file. When you type ls in your terminal, does the name of your Python file show up? If not, hover over the tab in VSCode (it's close to the top of the editor) and see what path appears. Then in your terminal type cd (short for "change directory") and then the path that you saw, minus the <your filename here>.py bit. Type ls again, and you should see your Python file. Now you can type python <your filename here>.py to run it (provided you have Python installed).
You could also run the IDLE by just typing python in your terminal. This will allow you to write your code line-by-line and immediately evaluate it, but it's easier to write in VSCode and then run it with the method I described before.

how to disable pdb.set_trace() without stopping python program and edit the code

I suspect that I have issue in one of my loops, so I setup a break points with pdb.set_trace()
import pdb
for i in range(100):
print("a")
pdb.set_trace()
print("b")
after check variable in this loop for a few times, I decide continue this programming without further breaks. So I try to get the break number with b command, no breaks listed. I guess this line of code don't setup a break point. but How Do I get ride of this "break points" without stopping the program and change the code?
to my knowledge, you could not bypass set_trace, but you could neutralize it, once debugger stopped, type:
pdb.set_trace = lambda: 1
then continue, it wont break again.
Setting a breakpoint (requires Python 3.7):
breakpoint()
Disabling breakpoints set with the breakpoint() function:
import os
os.environ["PYTHONBREAKPOINT"] = "0"
Long story:
In the 3.7 version of Python, the breakpoint() built-in function for setting breakpoints was introduced. By default, it will call pdb.set_trace(). Also, since the 3.7 version of Python the PYTHONBREAKPOINT environment variable is available. It is considered when the breakpoint() function is used.
So, in order to disable these breakpoints (set with the breakpoint() function), one can just set the PYTHONBREAKPOINT environment variable like this:
import os
os.environ["PYTHONBREAKPOINT"] = "0"
It may be useful to mention here sys.breakpointhook() which was also added in the 3.7 version of Python and allows to customize breakpoints behavior.
Unfortunately pdb is missing a bunch of functionality (even basic stuff like display lists), and you've found another example of that here. The good news is that pdb++ is a great drop-in replacement for pdb, and one of the things it solves is exactly the problem of disabling set_trace. So you can simply do:
pip install pdbpp
and then at the (Pdb++) prompt, type
pdb.disable()
Easy! And you will get lots of other useful goodies on top of that.
It is possible to start a Python script without PDB control but then hit a stray set_trace() left there. To prevent breaking into debugger every time set_trace() is encountered, a similar trick as above (changing the symbol's reference to point to a harmless function) can be applied.
However, the namespace of the debuggee has to be modified, not one of the debugger itself. Simply overwriting pdb.set_trace = lambda:1 or set_trace = lambda:1 did not work for me.
The following trick worked from the pdb prompt:
pdb> globals()['set_trace'] = lambda:1
This line first calls globals() to get access to a dict of the program under debugging, and then modifies the reference of set_trace there.
One way around this is to not write the breakpoints in the script itself, but rather set breakpoints when you start python with python -m pdb my_script.py
You then get into a prompt first, before execution of the script starts, and you can write for example
(Pdb) b 321
to set a breakpoint on line 321 (you can also specify file and specify conditions b 321, i == 50)
Then
(Pdb) c
(for continue) to start the execution of the actual script. The breakpoints you set in this way, you can clear when you're done with them with:
(Pdb) cl
(for clear)

breakpoint on all files from a certain directory

I like to use ipdb to debug my code. I know we could stop the code on a file on a specific line with b(reak) file:lineno. That command will set a breakpoint in file at line 'no'.
Actually, I have inserted import ipdb; ipdb.set_trace() on a specific file. Each time I use the command s(tep), it executes and step into functions. My problem is it is too slow before seeing what I want to see. The stacktrace showed me lines I do not necessarily want to see. Then I was thinking to put a breakpoint on all files from a certain directory, i.e., b mydirectory/**. Therefore, eachtime I will execute c, it will show me all lines I want to see. However, I can't execute such command (i.e., b mydirectory/**). Could anyone have a solution to this problem?
Thanks!
P.S. The following picture show ton of those irrelevant files I don't want to see. In fact, it is normal to see those files, because I am working on a django project.
Please tell me if the question is unclear
import pdb; pdb.Pdb(skip=['mydirectory.*']).set_trace()
mydirectory have to be a python module, here is more info from the documentaion
The skip argument, if given, must be an iterable of glob-style module
name patterns. The debugger will not step into frames that originate
in a module that matches one of these patterns. [1]
source: https://docs.python.org/2/library/pdb.html#pdb.Pdb

Step-by-step debugging with IPython

From what I have read, there are two ways to debug code in Python:
With a traditional debugger such as pdb or ipdb. This supports commands such as c for continue, n for step-over, s for step-into etc.), but you don't have direct access to an IPython shell which can be extremely useful for object inspection.
Using IPython by embedding an IPython shell in your code. You can do from IPython import embed, and then use embed() in your code. When your program/script hits an embed() statement, you are dropped into an IPython shell. This allows the full inspection of objects and testing of Python code using all the IPython goodies. However, when using embed() you can't step-by-step through the code anymore with handy keyboard shortcuts.
Is there any way to combine the best of both worlds? I.e.
Be able to step-by-step through your code with handy pdb/ipdb keyboard shortcuts.
At any such step (e.g. on a given statement), have access to a full-fledged IPython shell.
IPython debugging as in MATLAB:
An example of this type of "enhanced debugging" can be found in MATLAB, where the user always has full access to the MATLAB engine/shell, and she can still step-by-step through her code, define conditional breakpoints, etc. From what I have discussed with other users, this is the debugging feature that people miss the most when moving from MATLAB to IPython.
IPython debugging in Emacs and other editors:
I don't want to make the question too specific, but I work mostly in Emacs, so I wonder if there is any way to bring this functionality into it. Ideally, Emacs (or the editor) would allow the programmer to set breakpoints anywhere on the code and communicate with the interpreter or debugger to have it stop in the location of your choice, and bring to a full IPython interpreter on that location.
What about ipdb.set_trace() ? In your code :
import ipdb; ipdb.set_trace()
update: now in Python 3.7, we can write breakpoint(). It works the same, but it also obeys to the PYTHONBREAKPOINT environment variable. This feature comes from this PEP.
This allows for full inspection of your code, and you have access to commands such as c (continue), n (execute next line), s (step into the method at point) and so on.
See the ipdb repo and a list of commands. IPython is now called (edit: part of) Jupyter.
ps: note that an ipdb command takes precedence over python code. So in order to write list(foo) you'd need print(list(foo)), or !list(foo) .
Also, if you like the ipython prompt (its emacs and vim modes, history, completions,…) it's easy to get the same for your project since it's based on the python prompt toolkit.
You can use IPython's %pdb magic. Just call %pdb in IPython and when an error occurs, you're automatically dropped to ipdb. While you don't have the stepping immediately, you're in ipdb afterwards.
This makes debugging individual functions easy, as you can just load a file with %load and then run a function. You could force an error with an assert at the right position.
%pdb is a line magic. Call it as %pdb on, %pdb 1, %pdb off or %pdb 0. If called without argument it works as a toggle.
(Update on May 28, 2016) Using RealGUD in Emacs
For anyone in Emacs, this thread shows how to accomplish everything described in the OP (and more) using
a new important debugger in Emacs called RealGUD which can operate with any debugger (including ipdb).
The Emacs package isend-mode.
The combination of these two packages is extremely powerful and allows one to recreate exactly the behavior described in the OP and do even more.
More info on the wiki article of RealGUD for ipdb.
Original answer:
After having tried many different methods for debugging Python, including everything mentioned in this thread, one of my preferred ways of debugging Python with IPython is with embedded shells.
Defining a custom embedded IPython shell:
Add the following on a script to your PYTHONPATH, so that the method ipsh() becomes available.
import inspect
# First import the embed function
from IPython.terminal.embed import InteractiveShellEmbed
from IPython.config.loader import Config
# Configure the prompt so that I know I am in a nested (embedded) shell
cfg = Config()
prompt_config = cfg.PromptManager
prompt_config.in_template = 'N.In <\\#>: '
prompt_config.in2_template = ' .\\D.: '
prompt_config.out_template = 'N.Out<\\#>: '
# Messages displayed when I drop into and exit the shell.
banner_msg = ("\n**Nested Interpreter:\n"
"Hit Ctrl-D to exit interpreter and continue program.\n"
"Note that if you use %kill_embedded, you can fully deactivate\n"
"This embedded instance so it will never turn on again")
exit_msg = '**Leaving Nested interpreter'
# Wrap it in a function that gives me more context:
def ipsh():
ipshell = InteractiveShellEmbed(config=cfg, banner1=banner_msg, exit_msg=exit_msg)
frame = inspect.currentframe().f_back
msg = 'Stopped at {0.f_code.co_filename} at line {0.f_lineno}'.format(frame)
# Go back one level!
# This is needed because the call to ipshell is inside the function ipsh()
ipshell(msg,stack_depth=2)
Then, whenever I want to debug something in my code, I place ipsh() right at the location where I need to do object inspection, etc. For example, say I want to debug my_function below
Using it:
def my_function(b):
a = b
ipsh() # <- This will embed a full-fledged IPython interpreter
a = 4
and then I invoke my_function(2) in one of the following ways:
Either by running a Python program that invokes this function from a Unix shell
Or by invoking it directly from IPython
Regardless of how I invoke it, the interpreter stops at the line that says ipsh(). Once you are done, you can do Ctrl-D and Python will resume execution (with any variable updates that you made). Note that, if you run the code from a regular IPython the IPython shell (case 2 above), the new IPython shell will be nested inside the one from which you invoked it, which is perfectly fine, but it's good to be aware of. Eitherway, once the interpreter stops on the location of ipsh, I can inspect the value of a (which be 2), see what functions and objects are defined, etc.
The problem:
The solution above can be used to have Python stop anywhere you want in your code, and then drop you into a fully-fledged IPython interpreter. Unfortunately it does not let you add or remove breakpoints once you invoke the script, which is highly frustrating. In my opinion, this is the only thing that is preventing IPython from becoming a great debugging tool for Python.
The best you can do for now:
A workaround is to place ipsh() a priori at the different locations where you want the Python interpreter to launch an IPython shell (i.e. a breakpoint). You can then "jump" between different pre-defined, hard-coded "breakpoints" with Ctrl-D, which would exit the current embedded IPython shell and stop again whenever the interpreter hits the next call to ipsh().
If you go this route, one way to exit "debugging mode" and ignore all subsequent breakpoints, is to use ipshell.dummy_mode = True which will make Python ignore any subsequent instantiations of the ipshell object that we created above.
You can start IPython session from pudb and go back to the debugging session as you like.
BTW, ipdb is using IPython behind the scenes and you can actually use IPython functionality such as TAB completion and magic commands (the one starts with %). If you are OK with ipdb you can start it from IPython using commands such as %run and %debug. ipdb session is actually better than plain IPython one in the sense you can go up and down in the stack trace etc. What is missing in ipdb for "object inspection"?
Also, python.el bundled with Emacs >= 24.3 has nice ipdb support.
Looks like the approach in #gaborous's answer is deprecated.
The new approach seems to be:
from IPython.core import debugger
debug = debugger.Pdb().set_trace
def buggy_method():
debug()
Prefixing an "!" symbol to commands you type in pdb seems to have the same effect as doing something in an IPython shell. This works for accessing help for a certain function, or even variable names. Maybe this will help you to some extent. For example,
ipdb> help(numpy.transpose)
*** No help on (numpy.transpose)
But !help(numpy.transpose) will give you the expected help page on numpy.transpose. Similarly for variable names, say you have a variable l, typing "l" in pdb lists the code, but !l prints the value of l.
You can start IPython from within ipdb.
Induce the ipdb debugger1:
import idpb; ipdb.set_trace()
Enter IPython from within in the ipdb> console2:
from IPython import embed; embed()
Return to the ipdb> console from within IPython:
exit
If you're lucky enough to be using Emacs, things can be made even more convenient.
This requires using M-x shell. Using yasnippet and bm, define the following snippet. This will replace the text ipdb in the editor with the set-trace line. After inserting the snippet, the line will be highlighted so that it is easily noticeable and navigable. Use M-x bm-next to navigate.
# -*- mode: snippet -*-
# name: ipdb
# key: ipdb
# expand-env: ((yas-after-exit-snippet-hook #'bm-toggle))
# --
import ipdb; ipdb.set_trace()
1 All on one line for easy deletion. Since imports only happen once, this form ensures ipdb will be imported when you need it with no extra overhead.
2 You can save yourself some typing by importing IPython within your .pdbrc file:
try:
from IPython import embed
except:
pass
This allows you to simply call embed() from within ipdb (of course, only when IPython is installed).
Did you try this tip?
Or better still, use ipython, and call:
from IPython.Debugger import Tracer; debug_here = Tracer()
then you can just use
debug_here()
whenever you want to set a breakpoint
the right, easy, cool, exact answer for the question is to use %run macro with -d flag.
In [4]: run -d myscript.py
NOTE: Enter 'c' at the ipdb> prompt to continue execution.
> /cygdrive/c/Users/mycodefolder/myscript.py(4)<module>()
2
3
----> 4 a=1
5 b=2
One option is to use an IDE like Spyder which should allow you to interact with your code while debugging (using an IPython console, in fact). In fact, Spyder is very MATLAB-like, which I presume was intentional. That includes variable inspectors, variable editing, built-in access to documentation, etc.
If you type exit() in embed() console the code continue and go to the next embed() line.
The Pyzo IDE has similar capabilities as the OP asked for. You don't have to start in debug mode. Similarly to MATLAB, the commands are executed in the shell. When you set up a break-point in some source code line, the IDE stops the execution there and you can debug and issue regular IPython commands as well.
It does seem however that step-into doesn't (yet?) work well (i.e. stopping in one line and then stepping into another function) unless you set up another break-point.
Still, coming from MATLAB, this seems the best solution I've found.
From python 3.2, you have the interact command, which gives you access to the full python/ipython command space.
Running from inside Emacs' IPython-shell and breakpoint set via pdb.set_trace() should work.
Checked with python-mode.el, M-x ipython RET etc.
Developing New Code
Debugging inside IPython
Use Jupyter/IPython cell execution to speed up experiment iterations
Use %%debug for step through
Cell Example:
%%debug
...: for n in range(4):
...: n>2
Debugging Existing Code
IPython inside debugging
Debugging a broken unit test: pytest ... --pdbcls=IPython.terminal.debugger:TerminalPdb --pdb
Debugging outside of test case: breakpoint(), python -m ipdb, etc.
IPython.embed() for full IPython functionality where needed while in the debugger
Thoughts on Python
I agree with the OP that many things MATLAB does nicely Python still does not have and really should since just about everything in the language favors development speed over production speed. Maybe someday I will contribute more than trivial bug fixes to CPython.
https://github.com/ipython/ipython/commit/f042f3fea7560afcb518a1940daa46a72fbcfa68
See also Is it possible to run commands in IPython with debugging?
If put import ipdb; ipdb.set_trace() at cell outside function, it will occur error.
Using %pdb or %debug, you can only see the filnal error result. You cannot see the code doing step by step.
I use following skill:
%%writefile temp.py
.....cell code.....
save the code of cell to file temp.py.
and then
%run -i -d temp.py, it will run the cell code by pdb .
-i: run the file in IPython’s namespace instead of an empty one.
-d: run your program under the control of pdb, the Python debugger.

How can I make ipdb show more lines of context while debugging?

By default, during debugging in IPython, ipdb shows one line above and one line below the current position in code.
Is there an easy way to make the area shown a bit bigger? I'd think it would be configurable, but haven't been able to find it.
You can type l in ipdb to show a few more lines of the current context
and you can keep hitting l and it continue revealing more lines from the file
If you want to show more lines of context around the current line you can type l to get the current line. And then type l curr_line - 10, curr_line + 10. Say I was on line 50 and I wanted to see the surrounding 20 lines. I would type: l 40,60 to see more.
As noted by #jrieke in a comment, you can also hit ll to get a bigger chunk of context. One nice thing about ll is it will print all the way back from the start of the current method (whereas consecutive ls reveal further lines below your breakpoint).
You can get more context by doing:
ipdb.set_trace(context=21)
Permanent context size
To permanently set context size, find the installation directory by doing
python -c 'import ipdb; print(ipdb)'
which will show you a __init__.py file. Open that file and find the line (which may also be found in IPDB's __main__.py:
def set_trace(frame=None, context=3):
change the 3 to however many context lines you want.
easy way to do this - 2022
figure out where you're loading ipdb from
import ipdb
print(ipdb.__file__)
open __main__.py from that folder
search for except (configparser.NoSectionError, configparser.NoOptionError):
below it is 3. Change that to your desired value
Why this is better than the proper way:
I don't need to learn a new configuration language
I don't need to create a new configfile
I don't need to debug why my configfile isn't being picked up
you never get tricked by file scoping/permissions/visibility since you are sure which ipdb module is being loaded (i.e. it covers virtualenvs too)
I don't have to talk to upstream and try to convince them to adopt this default.
There are several ways to configure it without changing any code.
If you want to have a persistent setting in your shell, you can use IPDB_CONTEXT_SIZE variable. Add the following to your .bashrc/.zshrc/etc.:
export IPDB_CONTEXT_SIZE=10
Thanks to N1ngu for pointing this out.
Keep in mind though, that this is implemented in ipdb itself, not in IPython, so while it will work when used with ipdb.set_trace(), it doesn't apply to the %debug magic.
Starting with IPython 7.21 you can also use context command in ipdb to change the number of backtrace lines shown:
import ipdb; ipdb.set_trace()
...
ipdb> context 10
ipdb> bt
You can put the following line in ~/.ipdb to make ipdb set it automatically:
context = 10
Apart from that, there's also the old context= argument in set_trace(), which makes it possible to set it at the time of running the debugger:
import ipdb; ipdb.set_trace(context=10)
# or, if you've set PYTHONBREAKPOINT=ipdb.set_trace in your environment
breakpoint(context=10)
Edit: it was implemented: https://stackoverflow.com/a/66474153/895245
As a quick complement to this other answer this is the one liner that you generally want to add to the code you want to debug:
__import__('ipdb').set_trace(context=21)
You likely want to add a shortcut for that from your editor, e.g. for Vim snipmat I have:
snippet ipd
__import__('ipdb').set_trace(context=21)
so I can type just ipd<tab> and it expands to the breakpoint. Then removing it is easy with dd since everything is contained in a single line.
Feature request for ipdb to increase the default context size: https://github.com/gotcha/ipdb/issues/147
Here's a patch to permanently set context for your program:
(works across set_trace and post_mortem)
def ipdb_patch(context = 11):
import ipdb
ipdbmain = ipdb.__main__
def _init_pdb(context=context, commands=[]):
try : p = ipdbmain.debugger_cls(context=context)
except TypeError : p = ipdbmain.debugger_cls()
p.rcLines.extend(commands)
return p
def set_trace(frame=None, context=context):
ipdbmain.wrap_sys_excepthook()
if frame is None : frame = ipdbmain.sys._getframe().f_back
p = ipdbmain._init_pdb(context).set_trace(frame)
if p and hasattr(p, 'shell') : p.shell.restore_sys_module_state()
ipdbmain._init_pdb = _init_pdb
ipdb.set_trace = set_trace
return ipdb
ipdb = ipdb_patch()
to add breakpoint() functionality simply add:
import sys
sys.breakpointhook = ipdb.set_trace
With that all the following commands have the right context size:
ipdb.set_trace()
breakpoint()
ipdb.post_mortem()
ipdb.pm()
%debug
It does not however work with this:
In [1]: %run -d file.py
If you know how to adjust that, please feel free to drop in comments
If you want to stop execution in a running system, as others said, use:
ipdb.set_trace(context=number_of_lines)
For running some function or an object's method modifying this context lines is a little bit tricky. The only way I found was:
ipdb.__main__._init_pdb(context=number_of_lines).runcall(callable, *args, **kwargs)
In case it serves someone.
Following the #erock618 way, in more recent ipdb versions you can use:
debugger_cls = ipdb.__main__._get_debugger_cls()

Categories