I have a function like this
def try_strip(s):
try:
return s.strip()
except Exception as e:
print(e)
# (I've tried inspect, traceback, logging, sys)
and if I call it somewhere like this
try_strip('could be a string or not')
then the exception line number would be the one in which the try_strip is defined.
Is there a way to get info about where was it called? Thank you in advance.
The Traceback module which is included with Python provides this functionality. According to its documentation it:
provides a standard interface to extract, format and print stack traces of Python programs. It exactly mimics the behaviour of the Python interpreter when it prints a stack trace.
The function traceback.format_stack() will return the stack trace information you need as a list of strings while the function traceback.print_stack() will print the stack trace information to the console. Below I have included some code which shows how you might use this in the example you provided:
import traceback
def try_strip(s):
try:
return s.strip()
except Exception as e:
traceback.print_stack()
stack_trace_info = traceback.format_stack()
# Code that write stack_trace_info to a log could go here
try_strip(5) # This will cause an error at runtime
For additional info on the Traceback module, please see https://docs.python.org/3/library/traceback.html .
Related
I'm trying to do something a little weird. I want to save a stack trace in Python, and then when I throw an exception on some later line, I want that exception to have the stack trace that I saved earlier, rather than the default traceback. I'm trying to give the illusion that an error was thrown from a different line than it actually was thrown from.
To make this a bit more concrete, I'd like to be able to do something like
class Pipeline:
def __init__(self):
saved_traceback = None
def m1(self):
# ... Do some work ....
saved_traceback = save_traceback()
def execute(self):
try:
# .... Do Some work
except Exception as e:
raise SpecialError(saved_traceback)
And then I'd run a script like:
foo = Pipeline()
foo.m1()
foo.execute()
And I want to implement execute in such a way that if an error is raised in its execution, the traceback instead points to the call to m1. This is part of a sort of lazy pipeline building domain specific language where no work happens until you call execute, so all error messages would come from execute. Instead, I want users to see an error that points to the method that added the faulty pipeline step.
You can use traceback.format_exc() to save the traceback as a string.
import traceback
try:
print(a)
except:
traceback_str = traceback.format_exc()
print(a) will fail with NameError because a was never defined. In the except block, the most recent traceback will be saved to traceback_str as a string.
In my experience programming with Java, I have become quite fond of the stack traces it generates when my code goes awry, but I feel that the traces generated by python are a bit lacking by comparison. For example, a trace in java might look like this:
java.lang.RuntimeException
at test.package.Example.c(Example.java:20)
at test.package.Example.b(Example.java:15)
at test.package.Example.a(Example.java:10)
Whereas a python trace might look like this:
Traceback (most recent call last):
File "example.py", line 10, in <module>
a()
File "example.py", line 2, in a
b()
File "example.py", line 5, in b
c()
File "example.py", line 8, in c
raise Exception
Exception
While both of these traces convey basically the same information, I personally find that the trace from java is easier to follow.
Is there a means to change the format python uses for printing its stack traces, or would that sort of change require me to create a custom exception handler at the root of my program?
using traceback module
import traceback
try:
x= 1/0
except Exception as e:
print(e)
traceback.print_exc()
There is a means to change the format Python uses to format its stack traces, and that is that you write your own formatter instead. There is only one built-in format.
You can assign your own function to sys.excepthook and it will act as a top-level exception handler that will get access to exceptions that were about to rise uncaught and cause the program to exit. There you can make use of the traceback object to format things however you like. Triptych's answer shows how to use the traceback module to get the info for each stack frame. extract_tb returns a 4-tuple of the filename, line number, function, and source text of the offending line, so if you want to not display the source text you could just throw that away and concatenate the rest. But you'll have to do the work of constructing whatever output you want to see.
If you really want to, you can reformat exception tracebacks with the traceback.extract_tb method.
ref: https://docs.python.org/2/library/traceback.html#traceback.extract_tb
I'm debugging a complex program that has a block like this:
try:
lots()
of()
deeply()
nested()
code()
except BaseException as e:
log_error(str(e))
The error message that comes out is just Config file missing but that's not much help to me.
I'd really like to see exactly were that message comes from.
(Note that the error string is from an external program, so it's not searchable.)
If I use traceback I only get to see the stack trace after it's been wound back to the handler, which is not useful. I'd like to see the traceback at the source of the exception.
Any ideas?
Thanks!
For debugging purposes you can use traceback module to print stack trace
import traceback
try:
lots()
of()
deeply()
nested()
code()
except BaseException as e:
print traceback.format_exc()
log_error(str(e))
I was looking to possibly try and save a traceback object and somehow pickle it to a file that I can access. An example of a use case for this is if I am submitting some python code to a farm computer to run and it fails, it would be nice to be able to open a session and access that traceback to debug the problem rather than just seeing a log of the traceback. I do not know if there is any sort of way to do this but thought it would be worth asking why it couldn't if so.
okay so you can use traceback.print_exception(type, value, traceback[, limit[, file]]) and save it in a text or json or you can refer to docs
if you find it helpful please mark it correct or upvote thanx..:)
Depending on how you've written your code, the try statement is probably your best answer. Since any error is just a class that inherits Python's builtin Exception, you can raise custom errors everywhere you need more information about a thrown error. You just need to rename your errors or pass in an appropriate string as the first argument. If you then try your code and use the except statement except CustomError as e, you can pull all the information you want out of e in the except statement as a regular instance. Example:
Your code would be:
def script():
try: codeblock
except Exception as e: raise Error1('You hit %s error in the first block'% e)
try: codeblock 2
except Exception as e: raise Error2('You hit %s error in the second block' % e)
try: script()
except Exception as e:
with open('path\to\file.txt','w') as outFile:
outFile.write(e)
The last part is really nothing more than creating your own log file, but you have to write it down somewhere, right?
As for using the traceback module mentioned above, you can get error information out of that. Any of the commands here can get you a list of tracebacks:
http://docs.python.org/2/library/traceback.html
On the otherhand, if you're trying to avoid looking at log files, the traceback module is only going to give you the same thing a log file would, in a different format. Adding your own error statements in your code gives you more information than a cryptic ValueError about what actually happened. If you print the traceback to your special error, it might give you still more information on your issue.
Is there a convenient way to get a more detailed stack trace on a Python exception? I'm hoping to find a wrapper utility/module or some other way to get a bit more info from the stack trace without having to actually modify the Python script that generates it. I'd like to be able to use this when running unit tests, or doctests, or when running utilities or inline scripts from the shell.
Specifically I think I'd like to have the values of local variables, or maybe just the values of the arguments passed to the innermost function in the stack trace. Some options to set the detail level would be nifty.
Not specifically related to your problem, but you might find this code useful -- automatically starts up the python debugger when a fatal exception occurs. Good for working with interactive code. It's originally from ActiveState
# code snippet, to be included in 'sitecustomize.py'
import sys
def info(type, value, tb):
if hasattr(sys, 'ps1') or not sys.stderr.isatty():
# we are in interactive mode or we don't have a tty-like
# device, so we call the default hook
sys.__excepthook__(type, value, tb)
else:
import traceback, pdb
# we are NOT in interactive mode, print the exception...
traceback.print_exception(type, value, tb)
print
# ...then start the debugger in post-mortem mode.
pdb.pm()
sys.excepthook = info
Did you have a look at traceback module?
http://docs.python.org/library/traceback.html
Also on SO:
Showing the stack trace from a running Python application
As mentionned by pyfunc, you can use the function in the traceback module but you only get a stacktrace.
If you want to inspect the stack you have to use the sys.exc_info() function and walk the traceback member and dump information from its frame (tb_frame). See the python Reference Manual for further information on these types.
Here is an example:
def killit(a):
a[10000000000000] = 1
def test(a):
killit(a)
def iterate_traceback(tb):
while tb is not None:
yield tb
tb = tb.tb_next
try:
test(tuple())
except Exception as e:
import sys
exception_info = sys.exc_info()
traceback = exception_info[2]
for tb in iterate_traceback(traceback):
print "-" * 10
print tb.tb_frame.f_code
print tb.tb_frame.f_locals
print tb.tb_frame.f_globals