Debugging django/unittest? - python

I'm wondering if anybody has a hint on how to debug a unittest, or any other piece of code in django, for that matter, using a debugger like winpdb?
I'm trying to to a
winpdb manage.py test photo
which runs my unittest for my photo app, but winpdb crashes. Are there alternatives? What is the best way to do this?
I'm running linux, ubuntu 10.10.

You can use pdb to debug your program.
import pdb
def some_function():
pdb.set_trace()
some_other_computation()
When the program hits the set_trace method, execution will pause, and you will be put into an interactive shell. You can then examine variables, and step through your code.

Look at pudb, it is a full-screen, console-based visual debugger for Python. Very nice for debugging with good console UI.
import pudb
def some_function():
pudb.set_trace()
some_other_computation()
You'll need to pass the -s option (eg: python manage.py test -s), to turn off output capturing (which prevents the debugger from starting).

Add following lines to your code:
import rpdb2;
rpdb2.start_embedded_debugger_interactive_password()
You can find more information here: http://winpdb.org/docs/embedded-debugging/

The problem is that django creates another process in which it runs the application under test. So you can not just use winpdb on your main django process.
You should put a call to rpdb2 debugger (winpdb internal debugger) just before the place you want test and attach with winpdb to that running debugger.
See a tutorial here: https://code.djangoproject.com/wiki/DebuggingDjangoWithWinpdb

Related

How do I debug through a gdb helper script written in python?

there may very well be an answer to this question, but it's really hard to google for.
you can add commands to gdb by writing them in python. I am interested in debugging one of those python scripts that's running in gdb session.
my best guess is to run gdb on gdb and execute the user added command and somehow magically break on the python program code?
has anybody done anything like this before? I don't know the mechanism by which gdb calls python code, so if it's not in the same process space as the gdb that's calling it, I don't see how I'd be able to set breakpoints in the python program.
or do I somehow get pdb to run in gdb? I guess I can put pdb.set_trace() in the python program, but here's the extra catch: I'd like to be able to do all this from vscode.
so I guess my question is: what order of what things do I need to run to be able to vscode debug a python script that was initiated by gdb?
anybody have any idea?
thanks.
so I figured it out. it's kinda neat.
you run gdb to debug your program as normal, then in another window you attach to a running python program.
in this case the running python program is the gdb process.
once you attach, you can set breakpoints in the python program, and then when you run commands in the first window where the gdb session is, if it hits a breakpoint in the python code, it will pop up in the second window.
the tipoff was that when you run gdb there does not appear to be any other python process that's a child of gdb or related anywhere, so I figured gdb must dynamically link to some python library so that the python compiler/interpreter must be running in the gdb process space, so I figured I'd try attaching to that, and it worked.

How to debug a django application in a comfortable way?

I'm currently debugging a django application by inserting import pdb; pdb.set_trace() in the code and using the debugger commands to navigate through running application.
The debugger shows the current line, but most of the time it is helpful to have a bit more context. Therefore I open the current file in an editor in another window.
Now whenever the flow changes to another class I need to manually open the new file in the editor. - This feels like there is an easier way to do this.
Is there any kind of IDE integration able to debug a running django application?
Is there some other way I am not yet aware of?
PyCharm can do this. Perhaps only the Professional edition which is not free, but has a 30-days trial.
To make your life easier, try IDE like PyCharm.
I use pdb or ipdb to debug simple python file, but they wouldn't be so useful in debugging complex Python scripts.
Also, django-debug-tools is a good tool to debug and optimize Django application.

Nice general way to always invoke python debugger upon exception

I'd like to have my debugger run post_mortem() any time an exception is encountered, without having to modify the source that I'm working on. I see lots of examples that involve wrapping code in a try/except block, but I'd like to have it always run, regardless of what I'm working on.
I worked on a python wrapper script but that got to be ugly and pretty much unusable.
I use pudb, which is API-equivalent to pdb, so a pdb-specific answer is fine. I run code from within my editor (vim) and would like to have the pm come up any time an exception is encountered.
It took a few months of not doing anything about it, but I happened to stumble upon a solution. I'm sure this is nothing new for the more experienced.
I have the following in my environment:
export PYTHONUSERBASE=~/.python
export PYTHONPATH=$PYTHONPATH:$PYTHONUSERBASE
And I have the following file:
~/.python/lib/python2.7/site-packages/usercustomize.py
With the following contents:
import traceback
import sys
try:
import pudb as debugger
except ImportError:
import pdb as debugger
def drop_debugger(type, value, tb):
traceback.print_exception(type, value, tb)
debugger.pm()
sys.excepthook = drop_debugger
__builtins__['debugger'] = debugger
__builtins__['st'] = debugger.set_trace
Now, whether interactively or otherwise, the debugger always jumps in upon an exception. It might be nice to smarten this up some.
It's important to make sure that you have no no-global-site-packages.txt in your site-packages. This will disable the usercustomize module with the default site.py (my virtualenv had a no-global-site-packages.txt)
Just in case it would help others, I left in the bit about modifying __builtins__. I find it quite handy to always be able to rely on some certain tools being available.
Flavor to taste.
A possible solution is to invoke pdb (I don't know about pudb, but I'll just assume it works the same) as a script:
python -m pdb script.py
Quoting the the documentation:
When invoked as a script, pdb will automatically enter post-mortem
debugging if the program being debugged exits abnormally. After
post-mortem debugging (or after normal exit of the program), pdb will
restart the program.
A solution for pdb since Python 3.2 is to start the program under the debugger via -m pdb and tell pdb to continue via -c c:
python3 -m pdb -c c program.py
Quoting the pdb documentation:
When invoked as a script, pdb will automatically enter post-mortem debugging if the program being debugged exits abnormally. After post-mortem debugging (or after normal exit of the program), pdb will restart the program.
As-of pudb 2019.2: according to the pudb documentation, the official way involves changing your code a bit (and even then, I don't end up in post-mortem mode if I just run python3 program.py!):
To start the debugger without actually pausing use:
from pudb import set_trace; set_trace(paused=False)
at the top of your code. This will start the debugger without breaking, and run it until a predefined breakpoint is hit. You can also press b on a set_trace call inside the debugger, and it will prevent it from stopping there.
Although it is possible to start the program properly under the debugger via python3 -m pudb.run program.py, pudb's command-line args do not support anything like pdb's -c c. The pudb's --pre-run=COMMAND is for external commands, not pudb commands.
What I currently do is run python3 -m pudb.run program.py without mentioning pudb or set_tracein program.py at all and press c on the keyboard. This way pudb enters its post-mortem mode upon any unhandled exception. This however only works well when I know that the exception will be reproduced. For hunting down sporadically occuring exceptions I go back to the pdb solution.

Is there a way of using breakpoints in python?

I am just wondering if there is a way to add breakpoints in IDLE so that I can stop at a point in my script and write other lines in the idle shell for testing. If not, is there other software that can do this?
you can add the line
import pdb; pdb.set_trace()
anywhere in your code, when reached it will drop you into a debug shell. so useful i have an emacs shortcut to add the snippet.
you may also want to look at ipdb, and use
import ipdb; ipdb.set_trace()
instead
http://docs.python.org/library/pdb.html
If you are running Windows, you might look at PyScripter if you want a development environment with more features than IDLE.

Can I debug with python debugger when using py.test somehow?

I am using py.test for unit testing my python program. I wish to debug my test code with the python debugger the normal way (by which I mean pdb.set_trace() in the code) but I can't make it work.
Putting pdb.set_trace() in the code doesn't work (raises IOError: reading from stdin while output is captured). I have also tried running py.test with the option --pdb but that doesn't seem to do the trick if I want to explore what happens before my assertion. It breaks when an assertion fails, and moving on from that line means terminating the program.
Does anyone know a way to get debugging, or is debugging and py.test just not meant to be together?
it's real simple: put an assert 0 where you want to start debugging in your code and run your tests with:
py.test --pdb
done :)
Alternatively, if you are using pytest-2.0.1 or above, there also is the pytest.set_trace() helper which you can put anywhere in your test code. Here are the docs. It will take care to internally disable capturing before sending you to the pdb debugger command-line.
I found that I can run py.test with capture disabled, then use pdb.set_trace() as usual.
> py.test --capture=no
============================= test session starts ==============================
platform linux2 -- Python 2.5.2 -- pytest-1.3.3
test path 1: project/lib/test/test_facet.py
project/lib/test/test_facet.py ...> /home/jaraco/projects/project/lib/functions.py(158)do_something()
-> code_about_to_run('')
(Pdb)
The easiest way is using the py.test mechanism to create breakpoint
http://pytest.org/latest/usage.html#setting-a-breakpoint-aka-set-trace
import pytest
def test_function():
...
pytest.set_trace() # invoke PDB debugger and tracing
Or if you want pytest's debugger as a one-liner, change your import pdb; pdb.set_trace() into import pytest; pytest.set_trace()
Similar to Peter Lyon's answer, but with the exact code you need for pytest, you can add the following to the bottom of your pytest module (my_test_module.py) :
if __name__ == "__main__":
pytest.main(["my_test_module.py", "-s"])
Then you can invoke the debugger from the command line:
pdb3 my_test_module.py
Boom. You're in the debugger and able to enter debugger commands. This method leaves your test code un-littered with set_trace() calls and will run inside pytest 'normally'.
Simply use: pytest --trace test_your_test.py.
This will invoke the Python debugger at the start of the test
I'm not familiar with py.test, but for unittest, you do the following. Maybe py.test is similar:
In your test module (mytestmodule.py):
if __name__ == "__main__":
unittest.main(module="mytestmodule")
Then run the test with
python -m pdb mytestmodule.py
You will get an interactive pdb shell.
Looking at the docs, it looks like py.test has a --pdb command line option:
https://docs.pytest.org/en/7.2.x/reference/reference.html#command-line-flags
Add and remove breakpoints without editing source files
Although you can add breakpoints by adding breakpoint() or set_trace() statements to your code, there are two issues with this approach:
Firstly, once you have started running your code, there is no way to remove your breakpoint. I often find that once I start running my code and reach an initial breakpoint, I want to place another one and remove the initial breakpoint. After breakpoint() drops me into the debugger I can add additional breakpoints, but I can't remove the initial one. Although this can be mitigated somewhat by putting the initial breakpoint statement higher up, if you have parametrised tests then even that is limited. I may find myself repeating cont very often.
Secondly, it requires changes to the source code. You need to remember to remove all breakpoint() commands before committing any code to version control, you have to remove them before switching branches, etc. I sometimes find I want to use the debugger to compare test runs between two branches, and having to edit the source code to add a breakpoint every time makes that a considerably slower and more error-prone exercise. I may even want to add a breakpoint in a library I'm calling, in which case the file I'm editing may not even me in my git repository but somewhere deep in my conda environment, increasing the risk of forgetting to remove it. Editing files to add break points is, in my humble opinion, ugly.
To add and remove breakpoints interactively without editing any source files, you can evoke pytest as follows (in the bash shell):
python -mipdb $(type -p pytest) -s test_fileset.py
The -s flag is crucial here, because it stops pytest from messing with stdin and stdout, and when running inside the debugger, pytest will fail to mess with stdin and stdout and everything will go wrong. The exact calling syntax will be different for different shells.

Categories

Resources