I have a long running Python program that raises exception at some point. Is there some way to run this from ipython session and stop on the exception so I could examine the live data?
You may want ipython -i yourscript.py, which will execute your script in the interpreter environment. But this won't let you inspect the local environment where the exception happened, for example local variables within a function – you'll just be able to inspect globals. You probably want this instead:
In [1]: %run test.py
<exception occurs>
In [2]: %debug test.py
If you're not familiar with using PDB, check out some docs first.
Edit thanks to Thomas K
yes, depending on how you are setup. you can import your program and run it like any other module inside a try except block.
import yourprogram
try:
yourprogram.main_function(args)
except:
print "we blew up, investigate why"
If your program is not in a function you may need to put the try block around your import.
The problem with this approach is that the variables you are wanting to look at may be no longer in scope. I usually use print statements or log messages at various points to figure out what is not looking like I am expecting.
Related
When debugging scripts in Python (2.7, running on Linux) I occasionally inject pdb.set_trace() (note that I'm actually using ipdb), e.g.:
import ipdb as pdb
try:
do_something()
# I'd like to look at some local variables before running do_something_dangerous()
pdb.set_trace()
except:
pass
do_something_dangerous()
I typically run my script from the shell, e.g.
python my_script.py
Sometimes during my debugging session I realize that I don't want to run do_something_dangerous(). What's the easiest way to halt program execution so that do_something_dangerous() is not run and I can quit back to the shell?
As I understand it pressing ctrl-d (or issuing the debugger's quit command) will simply exit ipdb and the program will continue running (in my example above). Pressing ctrl-c seems to raise a KeyboardInterrupt but I've never understood the context in which it was raised.
I'm hoping for something like ctrl-q to simply take down the entire process, but I haven't been able to find anything.
I understand that my example is highly contrived, but my question is about how to abort execution from pdb when the code being debugged is set up to catch exceptions. It's not about how to restructure the above code so it works!
I found that ctrl-z to suspend the python/ipdb process, followed by 'kill %1' to terminate the process works well and is reasonably quick for me to type (with a bash alias k='kill %1'). I'm not sure if there's anything cleaner/simpler though.
From the module docs:
q(uit)
Quit from the debugger. The program being executed is aborted.
Specifically, this will cause the next debugger function that gets called to raise a BdbQuit exception.
What's the best way to monitor a python daemon to determine the cause of it quitting unexpectedly? Is strace my best option or is there something Python specific that does the job?
I would generally start by adding logging to it. At a minimum, have whatever is launching it capture stdout/stderr so that any stack traces are saved. Examine your except blocks to make sure you're not capturing exceptions silently.
You can use pdb:
python -m pdb myscript.py
Running your program like this will cause it to enter post-mortem debugging if it exits abnormally. If you have an idea where the problem is you can also use import pdb; pdb.set_trace() at the point you want to start debugging. Also logging profusely helps.
As the answer above, try to add Logging, however be carefull if you are using python-daemon module it will not work with Logging module when logging to a file, so you should make the logging manually to a file.
Also, make your daemon restarts after it has failed by running it inside a loop and catch exceptions inside the loop.
Example:
while True:
try:
log_to_file("starting daemon")
run_daemon()
log_to_file("daemon stopped unexpectedly")
sleep(1)
except Exception as err:
log_to_file(err)
I have a python function that I'm calling from inside an iPython session.
In a very specific situation, in which a conditional in a certain line comes out as True, the script consistently drops into a pdb debug mode.
There is no trace or any other indication of a problem with the code, and as soon as I type c to continue, the code continues perfectly well.
The script doesn't include any import pdb not to mention a set_trace()...
Any ideas what could account for this?
Depending on your ipython config it automatically goes into PDB if an exception is raised.
Seems like there was a import pdb; pdb.set_trace() line in the code after all, which I missed due to source control issues.
I'm looking for a way to debug a python exception "retrospectively". Essentially if my program raises an exception that isn't handled, I want it to save off the program state so I can go back later and debug the problem.
I've taken a look at the pdb docs, and it seems that you can do this, but only if you can interact with the program at the point of the exception. This won't work for me as the program will be run in the background (without a controlling terminal).
My first (doomed!) approach was to put a try/except block at the highest level of my program, and in the except block extract the traceback object from the current exception and write it to disk using pickle. I planned to then write a separate program that would unpickle the object and use pdb.post_mortem to debug the crashed program. But traceback objects aren't pickleable, but I wouldn't expect that to work anyway, as it wouldn't save off the entire program state.
As far as I know, there isn't any way to do what you're asking. That said, it sounds like you might be looking for a remote debugger. There are a couple of options:
rconsole - This isn't really a debugger, but it allows you to get an interactive prompt inside another process. This can be useful for debugging purposes. I haven't tried this, but it looks relatively straightforward.
rpdb2's embedded debugger - This lets you start a debugger and then connect to it from another shell.
What you can do is use twisted.python and write the traceback to a file, it gives you an exact traceback including the exception
At the moment the exception is caught, before the stack is unwound, the state is available for inspection with the inspect module: http://docs.python.org/2/library/inspect.html
Generically you would use inspect.getinnerframes on your traceback object. The local variables in each stack frame are available as .f_locals so you can see what they are.
The hard part is serializing all of them correctly: depending on what types you have in the local scope you may or may not be able to pickle them, dump them to JSON, or whatever.
You could create an entirely separate execution environment in the top level:
myEnv = {}
myEnv.update(globals)
Then execute your code within that execution environment. If an exception occurs you have the traceback (stack) and all the globals, so you can pretty well reconstruct the program state.
I hope this helps (it helped me):
import logging, traceback
_logger = logging.getLogger(__name__)
try:
something_bad()
except Exception as error:
_logger.exception("Oh no!") # Logs original traceback
store_exception_somewhere(error)
Also, in Python 3 there are a few new options like raise new_exc from original_exc
or raise OtherException(...).with_traceback(tb).
I'm calling python -m pdb myapp.py, when an exception fires, and I'd normally be thrown back to the pdb interpreter to investigate the problem. However this exception is being thrown after I've called through curses.wrapper() and entered curses mode, rendering the pdb interpreter useless. How can I work around this?
James` answer is a good and I've upvoted it but I'd also consider trying to split the logic and presentation layers of my program. Keep the curses part a thin layer on top of a library and write a simple driver that invokes the correct routines to recreate the error. Then you can dive in and do what's necessary.
Another way I can think of is to create a function called debug or something that throws you back into the regular screen and invokes pdb. Then stick it just before the code that raises the exception and run your program. Something like
def debug(stdscr):
curses.nocbreak()
stdscr.keypad(0)
curses.echo()
curses.endwin()
import pdb; pdb.set_trace()
Apparently, this is similar to what is done with the curses.wrapper function. It's mentioned briefly at http://www.amk.ca/python/howto/curses/.
Not being familiar with Python, this may not be exactly what you want. But apparently, winpdb can attach to a script - just like gdb can to a running process (IIUC).
http://winpdb.org/docs/launch-time/
Don't be mislead by the name, it is platform independent.
use pyclewn
you can use pyclewn with vim.
or use pdb-clone,the core of pyclewn
its good ,its like gdb ,can remote debug