vscode with debugpy: Recursive mode like pdb missing? - python

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

Related

Python Debugging Using Pdb

I'm using a interactive graphical Python debugger with ipdb under the hood (Canopy's graphical debugger). The script I am working on has multiple imported modules and several calls to their respective functions. Whenever I attempt a debugging run, execution gets stuck somewhere within a call to an imported module's function (specifically subprocess). My two main questions are:
1) Does running in debug mode slow things down considerably? Is the code not actually stuck, but just running at a painfully slow rate?
2) Is there a way to completely pass over bits of code and run them as if I were not even debugging? I want to prevent the debugger from diving into subprocess and just execute it as if it were a normal run.
I might toss the graphical debugger and do everything from a terminal, but I would like to avoid that if I can because the graphical interface is really convenient and saves a lot of typing.
import pdb
a = "aaa"
pdb.set_trace()
b = "bbb"
c = "ccc"
final = a + b + c
print final
Your output when you run the code then it will start debugging and control will stop after a="aaa"
$ python abc.py
(Pdb) p a
'aaa'
(Pdb)
Thanks, Shashi

Is there an interpreter for Python similar to Pry for Ruby? [duplicate]

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!

Breakpoint-induced interactive debugging of Python with IPython

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.

How to drop into REPL (Read, Eval, Print, Loop) from Python code

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!

Debugging a pyQT4 app?

I have a fairly simple app built with pyqt4. I wanted to debug one of the functions connected to one of the buttons in my app. However, when I do the following
python -m pdb app.pyw
> break app.pyw:55 # This is where the signal handling function starts.
things don't quite work like I'd hope. Instead of breaking in the function where I've set the breakpoint and letting me step through it, the debugger enters an infinite loop printing out QCoreApplication::exec: The event loop is already running and I am unable to input anything. Is there a better way to do this?
You need to call QtCore.pyqtRemoveInputHook. I wrap it in my own version of set_trace:
def debug_trace():
'''Set a tracepoint in the Python debugger that works with Qt'''
from PyQt4.QtCore import pyqtRemoveInputHook
# Or for Qt5
#from PyQt5.QtCore import pyqtRemoveInputHook
from pdb import set_trace
pyqtRemoveInputHook()
set_trace()
And when you are done debugging, you can call QtCore.pyqtRestoreInputHook(), probably best when you are still in pdb, and then after you hit enter, and the console spam is happening, keep hitting 'c' (for continue) until the app resumes properly. (I had to hit 'c' several times for some reason, it kept going back into pdb, but after hitting it a few times it resumed normally)
For further info Google "pyqtRemoveInputHook pdb". (Really obvious isn't it? ;P)
I had to use a "next" command at the trace point to get outside of that function first. For that I made a modification of the code from mgrandi:
def pyqt_set_trace():
'''Set a tracepoint in the Python debugger that works with Qt'''
from PyQt4.QtCore import pyqtRemoveInputHook
import pdb
import sys
pyqtRemoveInputHook()
# set up the debugger
debugger = pdb.Pdb()
debugger.reset()
# custom next to get outside of function scope
debugger.do_next(None) # run the next command
users_frame = sys._getframe().f_back # frame where the user invoked `pyqt_set_trace()`
debugger.interaction(users_frame, None)
This worked for me. I found the solution from here : Python (pdb) - Queueing up commands to execute
In my tests, jamk's solution works, while the previous one, although simpler, does not.
In some situations, for reasons that are unclear to me, I've been able to debug Qt without doing any of this.

Categories

Resources