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.
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
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.
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
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.
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 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.
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.
Related
I am trying to configure vscode debugger for recursive debugging with
debugpy. In this regard:
I open a jupyter console and attach the vscode debugger to the kernel.
I am then able to call some function and let vscode stop at some breakpoint.
The ipython cell seems to be blocked now and won't let me input further commands.
Leaving the breakpoint brings the ipython cell back to life.
This behaviour is confusing, since I would rather expect to be able to
continue working with the console, that is evaluating statements,
create plots, ... while stopping at the breakpoint. In addition I'd
expect to debug further code recursively, i.e. to let vscode stop at
some other breakpoint and return later on to the first breakpoint.
With python pdb this is possible by executing the "debug 'code'"
command, which creates a nested pdb instance.
Is it possible to replicate the pdb behavaiour with vscode by
configuration, ie.:
Go to the next cell when the breakpoint is hit an allow user input in ipython.
Provide some interactive magic commands to control the debugger from ipython (e.g. debug 'code')
Thanks, Daniel
Follows an example:
Define some dummy module 'my_module.py':
def fun():
import pdb; pdb.set_trace()
print('fun')
def rec_fun():
import pdb; pdb.set_trace()
print('fun')
a = 1
import pdb; pdb.set_trace()
b = 2
Then run a python console.
Then enter in your terminal:
import my_module # This will stop at the breakpoint and allow user further user input in the console, e.g. `print(a)`
# press c to completely load the module
my_module.fun() # This will stop the debugger at the breakpoint inside function fun
import my_module # this will load the module for the debugger instance
debug my_module.rec_fun() # this will launch a nested debugger instance
# Press c+enter: The nested instance will stop at breakpoint inside rec_fun()
# Press c+enter: The debugger will move to the previous breakpoint
# Press c+enter: The debugger will leave and go back to normal REPL mode.
This workflow seems not to be possible with vscode/debugpy. The key point in my opinion is keeping the shell alive with pdb-debugger. Some interactive commands are a subsequent problem. Is it possible to configure pydebug accordingly? What do you think?
Thanks,
Daniel
I'm used to GDB, where b does that.
But in pdb, b just list breakpoints.
I can do b 123, but lazy to type 123.
Maybe a magic argument like b .?
I know PyCharm and __import__('pdb').set_trace(), just checking if there is an usable CLI alternative for those quick debugs.
if you accept adding a new pdb command, it is trivial:
def do_breakcurrent(self, arg):
cur_lineno = str(self.curframe.f_lineno)
return self.do_break(cur_lineno)
import pdb
pdb.Pdb.do_breakcurrent = pdb.Pdb.do_bc = do_breakcurrent
use breakcurrent or bc:
(Pdb) bc
Breakpoint 1 at /Users/georgexsh/workspace/so/52110534.py:11
if you want to put those code into .pdbrc to make it available automatically, need little tweak:
import pdb
pdb.Pdb.do_bc = lambda self,arg: self.do_break(str(self.curframe.f_lineno))
I like testing functions in the Python interpreter. Is it possible to debug a function in the Python interpreter when I want to see more than a return value and a side effect?
If so, could you show basic debugger operations (launching the function with arguments, setting breakpoint, next step, step into, watching variable)? If not, how would you debug a function another way?
The point is, I want to debug only a particular function which will be supplied with arguments. I don't want to debug whole module code.
thank you for advice
If you want to debug specific function you can using this -
>>> import pdb
>>> import yourmodule
>>> pdb.run('yourmodule.foo()')
over the command line. pdb.set_trace() should be added in your function to break there.
More info on pdb can be seen here - http://docs.python.org/library/pdb.html
See pdb module. Insert into code:
import pdb
pdb.set_trace()
... makes a breakpoint.
The code-to-debug does not need to be modified to include pdb.set_trace(). That call can be made directly in the interpreter just before the code-to-debug:
>>> import pdb
>>> pdb.set_trace(); <code-to-debug>
For example, given test_script.py with the following code:
def some_func(text):
print 'Given text is {}'.format(repr(text))
for index,char in enumerate(text):
print ' '*index, char
an interpreter session to debug some_func using the debugger commands step-into (s), next (n) and continue (c) would look like:
>>> import pdb
>>> import test_script
>>> pdb.set_trace(); test_script.some_func('hello')
--Call--
> c:\src\test_script.py(1)some_func()
-> def some_func(text):
(Pdb) s
> c:\src\test_script.py(2)some_func()
-> print 'Given text is {}'.format(repr(text))
(Pdb) n
Given text is 'hello'
> c:\src\test_script.py(3)some_func()
-> for index,char in enumerate(text):
(Pdb) c
h
e
l
l
o
>>>
See the docs for the pdb module for more information on how to use the debugger: http://docs.python.org/library/pdb.html
Additionally, while using the debugger, the help command provides a nice list of commands and help <command> gives help specific to the given command.
I'd like to save the commands for a breakpoint in a .pdbrc, something like:
b 81
commands 1
pp foo.attr1
pp foo.attr2
end
b 108
commands 2
pp bar.attr1
pp bar.attr2
end
This would automate setting the environment for the debugging session. However, this does not work with python -m pdb script.py, because at the line commands 1, the pdb prompt starts and asks me for the commands for the first breakpoint, ignoring what I wrote in .pdbrc; further, it raises a NameError after I type end at the pdb prompt, because of foo.attr1, foo.attr2 and even end. The same happens for the rest of the breakpoints, so I end up with them set but not their commands.
What would be the correct way to do this? Is it even possible?
You probably don't want this set every time you use pdb anywhere. My recommendation would be to set up an alias, such as:
alias setup_myproj b 81;; commands 1;; pp foo.attr1;; pp foo.attr2;; end
Then you can run setup_myproj when appropriate.
My first thought was that the command must be defined on one line:
commands 1;; pp foo.attr1;; pp foo.attr2;; end;;
However, it appears that this will only work at the prompt, and you will incorrectly get:
Usage : commands [bnum]
...
end
if you place the line above in a .pdbrc
Looking at pdb.py it appears that the author does not properly handle defining commands in a pdbrc.
I personally would just temporarily place the print lines in the code I was debugging while using pdbrc to save the breakpoints of interest to get around this.
More than ten years later, but, unfortunately, it looks like pdb still does not properly handle the end command when reading commands from a .pdbrc file. There's now a related issue for cpython.
In the meantime, for simple control flows, it may be possible to work around the issue, simply by not using the commands command. For example, you could do:
# set the breakpoints
b 81
b 108
# continue to the first breakpoint
continue
# execute commands at first breakpoint
pp foo.attr1
pp foo.attr2
# continue to the second breakpoint
continue
# execute commands at second breakpoint
pp bar.attr1
pp bar.attr2
...
Obviously this only works in simple cases where you know which breakpoint will be reached next.
Is there a way to programmatically force a Python script to drop into a REPL at an arbitrary point in its execution, even if the script was launched from the command line?
I'm writing a quick and dirty plotting program, which I want to read data from stdin or a file, plot it, and then drop into the REPL to allow for the plot to be customized.
I frequently use this:
def interact():
import code
code.InteractiveConsole(locals=globals()).interact()
You could try using the interactive option for python:
python -i program.py
This will execute the code in program.py, then go to the REPL. Anything you define or import in the top level of program.py will be available.
Here's how you should do it (IPython > v0.11):
import IPython
IPython.embed()
For IPython <= v0.11:
from IPython.Shell import IPShellEmbed
ipshell = IPShellEmbed()
ipshell() # this call anywhere in your program will start IPython
You should use IPython, the Cadillac of Python REPLs. See http://ipython.org/ipython-doc/stable/interactive/reference.html#embedding-ipython
From the documentation:
It can also be useful in scientific
computing situations where it is
common to need to do some automatic,
computationally intensive part and
then stop to look at data, plots, etc.
Opening an IPython instance will give
you full access to your data and
functions, and you can resume program
execution once you are done with the
interactive part (perhaps to stop
again later, as many times as needed).
You can launch the debugger:
import pdb;pdb.set_trace()
Not sure what you want the REPL for, but the debugger is very similar.
To get use of iPython and functionality of debugger you should use ipdb,
You can use it in the same way as pdb, with the addition of :
import ipdb
ipdb.set_trace()
I just did this in one of my own scripts (it runs inside an automation framework that is a huge PITA to instrument):
x = 0 # exit loop counter
while x == 0:
user_input = raw_input("Please enter a command, or press q to quit: ")
if user_input[0] == "q":
x = 1
else:
try:
print eval(user_input)
except:
print "I can't do that, Dave."
continue
Just place this wherever you want a breakpoint, and you can check the state using the same syntax as the python interpreter (although it doesn't seem to let you do module imports).
It's not very elegant, but it doesn't require any other setup.
Great answers above, but if you would like this functionality in your IDE. Using Visual Studio Code (v1.5.*) with Python Setup:
Highlight the lines you would like to run and
right click and select Run Selection/Line in Interactive Window from the drop down.
Press shift + enter on your keyboard.
Right click on the Python file you want to execute in the file explorer and select Run Current File in Interactive Window
This will launch an interactive session, with linting, code completion and syntax highlighting:
Enter the code you would like to evaluate, and hit shift + enter on your keyboard to execute.
Enjoy Python!