Logging custom exceptions Python - python

I have a simple try and except statement. However I want to use logger exception to log the exception. What is the best way of only have 1 line of code for the logger.exception. In the exception base class ?
try:
do_something()
except CustomBaseExecption, exc:
logger.exception("Exception Raised:")
raise GeneralError(exc)
except Exception as exc:
logger.exception("Exception Raised:")
raise GeneralError("Unknown Error")

Only thing that's changed between two code blocks is GeneralError argument. Let's put a conditional there.
try:
do_something()
except Exception as exc:
logger.exception("Exception Raised:")
raise GeneralError(exc if isinstance(exc, CustomBaseExecption) else "Unknown Error")

Related

Exceptions in Python(multiple try blocks)

I am new to python and I have been wondering if you can do something like this in python.
try:
something():
if it throws an exception then try this:
something1():
if it throws an exception again:
print(exception)
Of course you can.
try:
something()
except Exception as exp:
try:
something1()
except Exception as exp2:
print(exp, exp2)
raise exp # in case you want to raise the original exception

How to access re-raised exception in Python 3?

In Python 3, there's a useful raise ... from ... feature to re-raise an exception. That said, how do you find the original (/ re-raised) exception from the raised exception? Here's a (silly) example with comments to demonstrate what I mean--
def some_func():
try:
None() # TypeError: 'NoneType' object is not callable
except as err:
raise Exception("blah") from err
try:
some_func()
except as err:
# how can I access the original exception (TypeError)?
It's in the __cause__ attribute of the raised exception. Taken from the docs on the raise statement it says regarding raise ... from ...:
The from clause is used for exception chaining: if given, the second expression must be another exception class or instance, which will then be attached to the raised exception as the __cause__ attribute (which is writable). If the raised exception is not handled, both exceptions will be printed.
So, in your given scenario, repring the __cause__ attribute:
def some_func():
try:
None() # TypeError: 'NoneType' object is not callable
except TypeError as err:
raise Exception("blah") from err
try:
some_func()
except Exception as er:
print(repr(er.__cause__))
Will print out:
TypeError("'NoneType' object is not callable",)
Whenever an exception is raised from an exception handler (the except clause), the original exception will bestored in new exception's __context__.
Whenever an exception is raised using from syntax, the exception specified in from will be saved in the __cause__ attribute of the new exception.
In the usual use case, that amounts to both __cause__ and __context__ containing the original exception:
def f():
try:
raise Exception('first exception')
except Exception as e:
raise Exception('second exception') from e
try:
f()
except Exception as e:
print('This exception', e)
print('Original exception', e.__context__)
print('Also original exception', e.__cause__)
Here is also an example of when __context__ is set:
try:
raise Exception('first exception')
except Exception as e:
raise Exception('second exception')
and an example of when __cause__ is set:
e = Exception('first exception')
raise Exception('second exception') from e

Python embedded exception handling

I have a code sample below, where I want to catch some exception:
in the main function:
try:
...
do_something()
except some_exception,e:
do_some_other_thing
in the do_something function
try:
...
except some_exception,e:
do_some_other_thing
So when I was testing it, I noticed that the exception was handled twice (once in do_somthing(), and once in the main function), is my observation accurate?
Is there a way to catch the exception that are only not captured by its function? Because there are two scenarios that I want to catch and they are somewhat wrapped into the same exception handling class(i.e. some_exception)
Your observation is inaccurate; there must be 2 places that raise some_exeption, or you are explicitly re-raising it.
Once an exception has correctly been caught, it will not be caught by other handlers higher up in the stack.
This is easiest shown with a little demonstration:
>>> try:
... try:
... raise AttributeError('foo')
... except AttributeError as e:
... print 'caught', e
... except AttributeError as e:
... print 'caught the same exception again?', e
...
caught foo
Only the inner except handler was invoked. If, on the other hand, we re-raise the exception, you'll see both handlers print a message:
>>> try:
... try:
... raise AttributeError('foo')
... except AttributeError as e:
... print 'caught', e
... raise e
... except AttributeError as e:
... print 'caught the same exception again?', e
...
caught foo
caught the same exception again? foo
As such, there is no need to have to handle 'exceptions that are not caught by the function'; you will only need to handle exceptions that were not already caught earlier.
Why not try it out and see what happens with a simple test?
def main():
try:
raise ValueError("in main!")
except ValueError as e:
print "caught exception",str(e)
#for fun, re-run with the next line uncommented and see what happens!
#raise
try:
main()
except ValueError:
print "caught an exception above main"
If you actually try this code, you'll notice that it only prints one message (inside the main function) demonstrating that an exception will not propagate upward once caught (unless you re-raise it in your except clause).

Print blank exception in python

I am trying to figure out how I would print an exception if I don't know what the exception is in the first place. How would I do the following?
try:
some_command
except:
print *full_exception_trace*
Like the tutorial says.
try:
something()
except SomeException as e:
something_else(e)
You may find traceback useful.
def exception(self)
try:
Something.objects.all()
except Exception, err:
print err.message #(if you want)
#raise err
raise # The 'raise' statement with no arguments inside an error
# handler tells Python to re-raise the exception with the
# original traceback intact
err.message will give you the reason of the exception
The traceback module's print_exc() function seems to be what you want. Docs

except block does not catch the exception in python

my code is like below
class Something(models.Model)
def exception(self)
try:
Something.objects.all()
except Exception():
raise Exception()
called this method from testcases ,its working but i need to raise exception ,it does not catch the exception
and here is my test case
def test_exception(self):
instance = Something()
instance.exception()
its working fine but i need to raise exception from except block
This line:
except Exception():
should be:
except Exception:
def exception(self)
try:
Something.objects.all()
except Exception, err:
#print err.message (if you want)
raise err
This will catch the error and print the exact msg if required.
Why catch the Exception just to re-raise it?
If you are not doing anything in the except suite except re-raising the exception, then simply do not catch the exception in the first place:
#staticmethod
def exception():
Something.objects.all()
If you are doing something nontrivial inside the except suite, then:
def exception(self):
try:
Something.objects.all()
except Exception:
# do something (with self?)
raise
Then, to test that the exception method raises an Exception:
def test_exception(self):
instance = Something()
self.assertRaises(Exception, instance.exception)
This depends on Something.objects.all() raising Exception.
PS. If exception does not depend on self, then it is best to remove it from the argument list and make exception a staticmethod.
PPS. Exception is a very broad base exception class. A more specific exception would be more helpful for debugging, and allow other code to catch this specific exception instead of forcing it to handle any possible Exception.

Categories