How to determine the origin of a Python exception - python

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))

Related

Get line number of a python function call in exception

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 .

Python Behave raise test failure on except [duplicate]

I want to explicitly fail the step in behave when I encounter an exception
eg. I am writing the code according to behave documentation -
from behave import *
#when('verify test fails.*?(?P<param_dict>.*)')
def test_logger(context, param_dict):
try:
logger.info("testing the logger. this is info message")
logger.info(1/0)
except Exception as e:
logger.error("arrived at exception: "+str(e))
fail("failed with exception: "+str(e))
but it throws this error:
NameError: name 'fail' is not defined
I tried other ways too, but nothing works
eg. context.failed = True (did not work either)
If I do not try to fail explicitly, final test result becomes PASS even if it goes in exception block ...which is weird.
context.failed is only an attribute set by Behave and doesn't do anything as is. It's an information attribute, and while you can use it to determine a fail-case and throw an assertion error, it will not do anything on it's own. See context.failed
As for the fail method you've mentioned, it is probably from the unittest module, as seen here. This module is used in Behave's development tests (see their Github) as well. I'll agree though, that this should be clarified in their documentation.
To fix your error you'd need to import the unittest module. To explicitly fail the step, you'd just raise the exception after you've logged your message, something like this:
except Exception as e:
logger.error("arrived at exception: "+str(e))
fail("failed with exception: "+str(e))
raise
As #Verv mentioned in their answer, a behave step will be marked as failed whenever an exception is thrown, so you could just re-raise the exception.
However, behave will show the backtrace for normal exceptions, whereas you probably just want to show a specific failure message.
For that, raise an AssertionError. In your code, that would look like this:
except Exception as e:
logger.error("arrived at exception: " + str(e))
raise AssertionError("failed with exception: " + str(e))
If behave encounters an AssertionError, it will fail the step, display the message you instantiate the error with, but not display other exception stuff.

How to build an exception that points to a saved python traceback?

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.

Any way to save a traceback object in Python

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.

catching an IOError in python

I wrote a method that does some stuff and catches bad filenames. what should happen is if the path doesn't exist, it throws an IOError. however, it thinks my exception handling is bad syntax... why??
def whatever():
try:
# do stuff
# and more stuff
except IOError:
# do this
pass
whatever()
but before it even gets to calling whatever(), it prints the following:
Traceback (most recent call last):
File "", line 1, in
File "getquizzed.py", line 55
except IOError:
^
SyntaxError: invalid syntax
when imported...help?!
Check your indenting. This unhelpful SyntaxError error has fooled me before. :)
From the deleted question:
I'd expect this to be a duplicate, but I couldn't find it.
Here's Python code, expected outcome of which should be obvious:
x = {1: False, 2: True} # no 3
for v in [1,2,3]:
try:
print x[v]
except Exception, e:
print e
continue
I get the following exception: SyntaxError: 'continue' not properly in loop.
I'd like to know how to avoid this error, which doesn't seem to be
explained by the continue documentation.
I'm using Python 2.5.4 and 2.6.1 on Mac OS X, in Django.
Thank you for reading
there's 1 more possible if you're privileged to have an older installation
and
you're using the 'as' syntax:
except IOError as ioe:
and
the parser's getting tripped up on 'as'.
Using as is the preferred syntax in Python 2.6 and better.
It's a syntax error in Python 2.5 and older. For pre-2.6, use this:
except IOError, ioe:
Just missing something in your try block, i.e. pass or anything, otherwise it gives an indentation error.
You will get a syntax error if you don't put something in side the try block.
You can put pass just to hold the space:
try:
# do stuff
# and more stuff
pass
except IOError:
# do this
pass

Categories

Resources