some_function() raises an exception while executing, so the program jumps to the except:
try:
some_function()
except:
print("exception happened!")
How do I see what caused the exception to occur?
The other answers all point out that you should not catch generic exceptions, but no one seems to want to tell you why, which is essential to understanding when you can break the "rule". Here is an explanation. Basically, it's so that you don't hide:
the fact that an error occurred
the specifics of the error that occurred (error hiding antipattern)
So as long as you take care to do none of those things, it's OK to catch the generic exception. For instance, you could provide information about the exception to the user another way, like:
Present exceptions as dialogs in a GUI
Transfer exceptions from a worker thread or process to the controlling thread or process in a multithreading or multiprocessing application
So how to catch the generic exception? There are several ways. If you just want the exception object, do it like this:
try:
someFunction()
except Exception as ex:
template = "An exception of type {0} occurred. Arguments:\n{1!r}"
message = template.format(type(ex).__name__, ex.args)
print message
Make sure message is brought to the attention of the user in a hard-to-miss way! Printing it, as shown above, may not be enough if the message is buried in lots of other messages. Failing to get the users attention is tantamount to swallowing all exceptions, and if there's one impression you should have come away with after reading the answers on this page, it's that this is not a good thing. Ending the except block with a raise statement will remedy the problem by transparently reraising the exception that was caught.
The difference between the above and using just except: without any argument is twofold:
A bare except: doesn't give you the exception object to inspect
The exceptions SystemExit, KeyboardInterrupt and GeneratorExit aren't caught by the above code, which is generally what you want. See the exception hierarchy.
If you also want the same stacktrace you get if you do not catch the exception, you can get that like this (still inside the except clause):
import traceback
print traceback.format_exc()
If you use the logging module, you can print the exception to the log (along with a message) like this:
import logging
log = logging.getLogger()
log.exception("Message for you, sir!")
If you want to dig deeper and examine the stack, look at variables etc., use the post_mortem function of the pdb module inside the except block:
import pdb
pdb.post_mortem()
I've found this last method to be invaluable when hunting down bugs.
Get the name of the class that exception object belongs:
e.__class__.__name__
and using print_exc() function will also print stack trace which is essential info for any error message.
Like this:
from traceback import print_exc
class CustomException(Exception): pass
try:
raise CustomException("hi")
except Exception as e:
print ('type is:', e.__class__.__name__)
print_exc()
# print("exception happened!")
You will get output like this:
type is: CustomException
Traceback (most recent call last):
File "exc.py", line 7, in <module>
raise CustomException("hi")
CustomException: hi
And after print and analysis, the code can decide not to handle exception and just execute raise:
from traceback import print_exc
class CustomException(Exception): pass
def calculate():
raise CustomException("hi")
try:
calculate()
except CustomException as e:
# here do some extra steps in case of CustomException
print('custom logic doing cleanup and more')
# then re raise same exception
raise
Output:
custom logic doing cleanup and more
And interpreter prints exception:
Traceback (most recent call last):
File "test.py", line 9, in <module>
calculate()
File "test.py", line 6, in calculate
raise CustomException("hi")
__main__.CustomException: hi
After raise original exception continues to propagate further up the call stack. (Beware of possible pitfall) If you raise new exception it caries new (shorter) stack trace.
from traceback import print_exc
class CustomException(Exception):
def __init__(self, ok):
self.ok = ok
def calculate():
raise CustomException(False)
try:
calculate()
except CustomException as e:
if not e.ok:
# Always use `raise` to rethrow exception
# following is usually mistake, but here we want to stress this point
raise CustomException(e.ok)
print("handling exception")
Output:
Traceback (most recent call last):
File "test.py", line 13, in <module>
raise CustomException(e.message)
__main__.CustomException: hi
Notice how traceback does not include calculate() function from line 9 which is the origin of original exception e.
You usually should not catch all possible exceptions with try: ... except as this is overly broad. Just catch those that are expected to happen for whatever reason. If you really must, for example if you want to find out more about some problem while debugging, you should do
try:
...
except Exception as ex:
print ex # do whatever you want for debugging.
raise # re-raise exception.
Most answers point to except (…) as (…): syntax (rightly so) but at the same time nobody wants to talk about an elephant in the room, where the elephant is sys.exc_info() function.
From the documentation of sys module (emphasis mine):
This function returns a tuple of three values that give information
about the exception that is currently being handled.
(…)
If no exception is being handled anywhere on the stack, a tuple
containing three None values is returned. Otherwise, the values
returned are (type, value, traceback). Their meaning is: type gets the
type of the exception being handled (a subclass of BaseException);
value gets the exception instance (an instance of the exception type);
traceback gets a traceback object (see the Reference Manual) which
encapsulates the call stack at the point where the exception
originally occurred.
I think the sys.exc_info() could be treated as the most direct answer to the original question of How do I know what type of exception occurred?
These answers are fine for debugging, but for programmatically testing the exception, isinstance(e, SomeException) can be handy, as it tests for subclasses of SomeException too, so you can create functionality that applies to hierarchies of exceptions.
Unless somefunction is a very bad coded legacy function, you shouldn't need what you're asking.
Use multiple except clause to handle in different ways different exceptions:
try:
someFunction()
except ValueError:
# do something
except ZeroDivision:
# do something else
The main point is that you shouldn't catch generic exception, but only the ones that you need to. I'm sure that you don't want to shadow unexpected errors or bugs.
In Python 2, the following are useful
except Exception, exc:
# This is how you get the type
excType = exc.__class__.__name__
# Here we are printing out information about the Exception
print 'exception type', excType
print 'exception msg', str(exc)
# It's easy to reraise an exception with more information added to it
msg = 'there was a problem with someFunction'
raise Exception(msg + 'because of %s: %s' % (excType, exc))
Use type class and as statement
try:#code
except Exception as e:
m=type(e)
#m is the class of the exception
strm=str(m)
#strm is the string of m
Hope this will help a little more
import sys
varExcepHandling, varExcepHandlingZer = 2, 0
try:
print(varExcepHandling/varExcepHandlingZer)
except Exception as ex:
print(sys.exc_info())
'sys.exc_info()' will return a tuple, if you only want the exception class name use 'sys.exc_info()[0]'
Note:- if you want to see all the exception classes just write dir(__builtin__)
Here's how I'm handling my exceptions. The idea is to do try solving the issue if that's easy, and later add a more desirable solution if possible. Don't solve the issue in the code that generates the exception, or that code loses track of the original algorithm, which should be written to-the-point. However, pass what data is needed to solve the issue, and return a lambda just in case you can't solve the problem outside of the code that generates it.
path = 'app.p'
def load():
if os.path.exists(path):
try:
with open(path, 'rb') as file:
data = file.read()
inst = pickle.load(data)
except Exception as e:
inst = solve(e, 'load app data', easy=lambda: App(), path=path)()
else:
inst = App()
inst.loadWidgets()
# e.g. A solver could search for app data if desc='load app data'
def solve(e, during, easy, **kwargs):
class_name = e.__class__.__name__
print(class_name + ': ' + str(e))
print('\t during: ' + during)
return easy
For now, since I don't want to think tangentially to my app's purpose, I haven't added any complicated solutions. But in the future, when I know more about possible solutions (since the app is designed more), I could add in a dictionary of solutions indexed by during.
In the example shown, one solution might be to look for app data stored somewhere else, say if the 'app.p' file got deleted by mistake.
For now, since writing the exception handler is not a smart idea (we don't know the best ways to solve it yet, because the app design will evolve), we simply return the easy fix which is to act like we're running the app for the first time (in this case).
To add to Lauritz's answer, I created a decorator/wrapper for exception handling and the wrapper logs which type of exception occurred.
class general_function_handler(object):
def __init__(self, func):
self.func = func
def __get__(self, obj, type=None):
return self.__class__(self.func.__get__(obj, type))
def __call__(self, *args, **kwargs):
try:
retval = self.func(*args, **kwargs)
except Exception, e :
logging.warning('Exception in %s' % self.func)
template = "An exception of type {0} occured. Arguments:\n{1!r}"
message = template.format(type(e).__name__, e.args)
logging.exception(message)
sys.exit(1) # exit on all exceptions for now
return retval
This can be called on a class method or a standalone function with the decorator:
#general_function_handler
See my blog about for the full example: http://ryaneirwin.wordpress.com/2014/05/31/python-decorators-and-exception-handling/
You can start as Lauritz recommended, with:
except Exception as ex:
and then just to print ex like so:
try:
#your try code here
except Exception as ex:
print ex
Your question is: "How can I see exactly what happened in the someFunction() that caused the exception to happen?"
It seems to me that you are not asking about how to handle unforeseen exceptions in production code (as many answers assumed), but how to find out what is causing a particular exception during development.
The easiest way is to use a debugger that can stop where the uncaught exception occurs, preferably not exiting, so that you can inspect the variables. For example, PyDev in the Eclipse open source IDE can do that. To enable that in Eclipse, open the Debug perspective, select Manage Python Exception Breakpoints in the Run menu, and check Suspend on uncaught exceptions.
Use the below for both Exception type and Exception text
import sys
print(str(sys.exc_info()[0]).split(' ')[1].strip('>').strip("'")+"-"+(str(sys.exc_info()[1])))
if you want only exception type: Use -->
import sys
print(str(sys.exc_info()[0]).split(' ')[1].strip('>').strip("'"))
Thanks Rajeshwar
The actual exception can be captured in the following way:
try:
i = 1/0
except Exception as e:
print e
You can learn more about exceptions from The Python Tutorial.
Just refrain from catching the exception and the traceback that Python prints will tell you what exception occurred.
tl;dr
How to catch different exceptions of the same type but with different messages?
Situation
In ideal world I would handle exceptions like this:
try:
do_something()
except ExceptionOne:
handle_exception_one()
except ExceptionTwo:
handle_exception_two()
except Exception as e:
print("Other exception: {}".format(e))
But external code that I'm using can can throw, in my usage, two exceptions. Both are ValueErrors but have different message. I'd like to differentiate handling them. This is the approach that I tried to take (for easier presentation of my idea I raise AssertionError):
try:
assert 1 == 2, 'test'
except AssertionError('test'):
print("one")
except AssertionError('AssertionError: test'):
print("two")
except Exception as e:
print("Other exception: {}".format(e))
but this code always goes to the last print() and gives me
Other exception: test
Is there a way to catch exceptions this way? I'm assuming this is possible because Python lets me specify MESSAGE when catching exception ExceptionType('MESSAGE') but in practice I didn't manage to make it work. I also didn't find a definitive answer in the docs.
I would go for something like this:
try:
do_the_thing()
except AssertionError as ae:
if "message A" in ae.value:
process_exception_for_message_A()
elif "message B" in ae.value:
process_exception_for_message_B()
else:
default_exception_precessing()
I have code that's a bit like this:
try:
# do stuff
except SomeSpecificException as sse:
if sse.some_property == some_special_value:
# handle the exception in a special way
else:
handle_exception_normally()
except:
handle_exception_normally()
I want to catch the specific exception and handle it in a special way, but only if it has a particular property. If it doesn't have that property, I want it to be handled just like any other exception (logging, screaming, etc.)
The code above works, but if possible, I want to avoid repeating handle_exception_normally() (DRY and all that).
Just putting raise in the else clause of the first except block does not work. A parent try block would catch that, but the catch-all clause in the same block will not.
I could nest two try blocks, but it's not very elegant; I'd rather just use
the code I have above.
Is there a better way?
Note that I'm using Python 3.
I would opt for:
try:
# do stuff
except Exception as e:
if e.args[0] == 'Discriminate Exception Here' and sse.some_property == some_special_value:
# handle the exception in a special way
else:
handle_exception_normally()
Moses Koledoye proposed:
try:
# do stuff
except Exception as e:
if getattr(e, 'some_property', None) == some_special_value:
# handle the exception in a special way
else:
handle_exception_normally()
Which is shorter but requires some_special_value to always be != None and attribute to be unique to your exception.
Examples of exception discrimination, with e.args[0]:
try:
5 / 0
except Exception as e:
print(e.args[0])
division by zero
With __class__.__name__:
try:
5 / 0
except Exception as e:
print(e.__class__.__name__)
ZeroDivisionError
With isinstance() (bit more CPU intensive) :
try:
5 / 0
except Exception as e:
isinstance(e, ZeroDivisionError)
True
I understand OP said they do not want to do this, but I'm throwing my lot in with the nested try block. I think it's the most readable way to go about this:
try:
try:
# do stuff
except SomeSpecificException as sse:
if sse.some_property == some_special_value:
# handle the exception in a special way
else:
raise
except:
handle_exception_normally()
How to decouple application from exceptions that creep in from used library dependencies?
[app] --uses--> [lib] --dependson--> [dependency]
/ /
x- <-propagates--o <---throwsexception--' /
\ /
`-----needstohandle,soimports-----> --'
The problem is from real pip code:
module A (req/req_set.py) depends on module B
module B (download) uses module C (requests)
module A imports module C to handle exception from C
How to encapsulate exception in module B? To remove dependency on C from module A? How to make sure that the cause and details of original exception are not lost? In other words how can I reraise the exception with a different name?
The snippet below does what is needed, but it it Python 3 only:
try:
dependency_call()
except DependencyError as exc:
raise LibraryError from exc
UPDATE: I am looking for Python 2 compatible solution, the Python 3 added raise ... from ... that does the trick almost good.
UPDATE 2: The goal of encapsulating exception is to catch it in [lib] and re-throw a new one to [app] preserving the stack trace so that debug tools can still walk up the code (for human-only solution the answer by Alex Thornton should be good).
You can catch an arbitrary exception by referring to the Exception base class:
except Exception as exc:
raise ApplicationError from exc
To get the from idiom to work in Python 2, you'll have to hack around with your custom exception:
class ApplicationError(Exception):
def __init__(self, cause, trace):
self.cause = cause
self.trace = trace
def __str__(self):
return '{origin}\nFrom {parent}'.format(origin=self.trace,
parent=self.cause)
And then raise it like this:
except Exception, exc:
raise ApplicationError(exc)
it will then print the cause when it is raised, which is also an attribute which you can access if you decide to catch the ApplicationError as well.
If i do get you right, you would like to decouple more strongly and eliminate:
from pip._vendor import requests
and:
except requests.HTTPError as exc:
you could do that by introducing a last-resort fallback handler as the
last except of all except clauses like:
try:...
except A:
... # here all your other exceptions
except Exception as exc: # the fall-back handler
if "HTTPError" in repr(exc):
# do whatever you want to do with the (assumed) request.HTTPError
# any other Exception with HTTPError in it's repr-string will be
# caught here
The draw-back is, that it's still a tight coupling and a clear violation of the
"law of Demeter", because you would need to know some internals of an object which
isn't even in the object-composition. So in some sense it's even worse now.
I'm currently writing a wrapper class. I want to be able to log exceptions properly but allow calling methods to be aware of exceptions which occur. My class looks like this:
import logging
log = logging.getLogger('module')
class MyAPIWrapper(library.APIClass):
def __init__(self):
self.log = logging.getLogger('module.myapiwrapper')
def my_wrapper_method(self):
try:
response = self.call_api_method()
return response.someData
except APIException, e:
self.log.exception('Oh noes!')
raise e #Throw exception again so calling code knows it happened
I'm a bit dubious about catching and exception just to log it and then re-raising it so the calling code can do something about it. What's the proper pattern here?
There is nothing wrong with catching to log. However, I'd recommend:
try:
response = self.call_api_method()
except APIException, e: # or 'as e' depending on your Python version
self.log.exception('Oh noes!')
raise #Throw exception again so calling code knows it happened
else:
return response.someData
By just doing a bare raise you preserve the full traceback info. It's also more explicit to put code that will only happen if you don't have an exception in the else clause, and it's clearer what line you're catching an exception from.
It would also be fine for the calling class to do the logging if it's handling the error anyway, but that may not be convenient for your app.
Edit: The documentation for try ... except ... else ... finally is under compound statements.
That method is correct, although instead of raise e you should just use raise, which will automatically re-raise the last exception. This is also one of the rare cases where using a blanket except is considered acceptable.
Here is an example very similar to what you are doing from the Python docs on Handling Exceptions:
The last except clause may omit the exception name(s), to serve as a wildcard. Use this with extreme caution, since it is easy to mask a real programming error in this way! It can also be used to print an error message and then re-raise the exception (allowing a caller to handle the exception as well):
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except IOError as (errno, strerror):
print "I/O error({0}): {1}".format(errno, strerror)
except ValueError:
print "Could not convert data to an integer."
except:
print "Unexpected error:", sys.exc_info()[0]
raise
You can just extend the standard Exception class and add the logger into there.
Like this:
class LoggedException(Exception):
""" An exception that also logs the msg to the given logger. """
def __init__(self, logger: logging.Logger, msg: str):
logger.error(msg)
super().__init__(msg)