Reputation: 16141
Is it possible to conditionally handle exceptions? I would like to be able to write a function so that the caller can decide who handles the exception.
Something like this:
def my_func(my_arg, handle_exceptions):
try:
do_something(my_arg)
except Exception as e if handle_exceptions:
print("my_func is handling the exception")
Upvotes: 27
Views: 18378
Reputation: 363566
Conditionally handle errors using a conditional statement in the except
block:
def my_func(my_arg, handle_exceptions):
try:
do_something(my_arg)
except Exception:
if handle_exceptions:
print("my_func is handling the exception")
raise
Re-raising the exception by using the bare raise
statement within the except block will not put another stack frame in the traceback.
Except statements can specify multiple exception types using a tuple. An empty tuple would mean don't handle any types. Ergo, you may specify the types to handle using a variable:
def my_func(my_arg, handle_exceptions):
errors = () if handle_exceptions else (Exception,)
try:
do_something(my_arg)
except errors:
print("my_func is handling the exception")
Upvotes: 4
Reputation: 11783
A nice looking technique to improve on the other answers is to wrap the conditional exception handling logic in a context manager that can be reused, like this:
from contextlib import contextmanager
@contextmanager
def ignore_errors_if(exception_type, skip_condition):
try:
yield
except exception_type, excn:
if skip_condition:
logging.debug("SKIPPING EXCEPTION %s" % excn) # etc...
pass
else:
raise excn
Then, in your code, you can say:
def some_function():
# ...
with ignore_errors_if(Exception, should_ignore_errors):
result = some_funciton_that_might_raise()
# Deal with result, although know that it might not be set...
Upvotes: 1
Reputation: 52798
You can re-raise the exception if you don't want to handle it:
def my_func(my_arg, handle_exceptions):
try:
do_something(my_arg)
except Exception, e:
if not handle_exceptions:
# preserve prior stack trace
raise
# Or, if you dont care about the stack prior to this point
#raise Exception(e)
# similarly, you can just re-raise e. The stack trace will start here though.
#raise e
else:
print "my_func is handling the exception"
Another option is to create your own exceptions that subclass Exception
(or a specific exception like urllib2.HTTPError
) and then only catch/throw (raise
) your custom exception:
class MyException(Exception):
def __init__(self, message):
self.message = message
class MyExceptionTwo(Exception):
def __init__(self, message):
self.message = message
def __repr__(self):
return "Hi, I'm MyExceptionTwo. My error message is: %s" % self.message
def something():
if not tuesday:
raise MyException("Error: it's not Tuesday.")
else:
raise MyExceptionTwo("Error: it's Tuesday.")
def my_func(my_arg):
try:
something()
except MyException, e:
print e.message
# Will pass MyExceptionTwo up the call chain
def my_other_func():
try:
my_func(your_arg)
except MyExceptionTwo, e:
print str(e)
# No need to catch MyException here since we know my_func() handles it
# but we can hadle MyExceptionTwo here
Upvotes: 33
Reputation: 31958
Yes. I prefer positive conditions when it makes sense:
def my_func(my_arg, handle_exceptions):
try:
do_something(my_arg);
except Exception, e:
if handle_exceptions:
print "my_func is handling the exception"
else:
raise
Upvotes: 2
Reputation: 69288
You have a two basic choices:
handle_exceptions
as a boolean, and re-raise if False
handle_exceptions
as the exceptions to handleAlong the boolean route you have two basic choices:
def my_func(my_arg, handle_exceptions):
try:
do_something(my_arg)
except Exception, e:
if not handle_exceptions:
raise
print "my_func is handling the exception"
or
def my_func(my_arg, handle_exceptions):
if handle_exceptions:
exceptions = ValueError, IndexError # or whatever
else:
exceptions = NoExceptions # None in 2.x, or custom Exception class in 3.x
try:
do_something(my_arg)
except exceptions, e:
print "my_func is handling the exception"
Along the 'treat handle_exceptions
as the exceptions to handle' route you can do this:
class NoExceptions(Exception):
'Dummy exception, never raised'
def my_func(my_arg, handle_exceptions=NoExceptions):
try:
do_something(my_arg)
except handle_exceptions, e:
print "my_func is handling the exception"
and you would call it like so:
my_func(some_arg, ValueError) # to handle ValueErrors
or
my_func(some_arg) # to not handle any exeptions
This has the advantage/disadvantage of the caller being able to specify which exceptions are handled. If you do take this last route you might also want to specify an exception handler, perhaps something like this:
def my_func(my_arg, handle_exceptions=NoExceptions, handler=None):
try:
do_something(my_arg)
except handle_exceptions, e:
if handler is not None:
handler(e)
else:
log_this_exception()
Upvotes: 2
Reputation: 226754
The question just doesn't have enough answers ;-)
Here's one more for the record books. Just create a dummy exception:
class NeverMatch(Exception):
'An exception class that is never raised by any code anywhere'
Then, use a conditional expression to decide whether to match the real exception or the placeholder exception (which never gets raised):
try:
do_something(my_arg)
except (Exception if handle_exceptions else NeverMatch) as e:
print 'I am handling it'
Upvotes: 20
Reputation: 9162
The exception type can be a variable.
def my_func(my_arg, handle_exceptions):
if handle_exceptions:
exc_type = Exception
else:
exc_type = None
try:
do_something(my_arg);
except exc_type, e:
print "my_func is handling the exception";
Obfuscated Python ("Pythonic"?) version:
def my_func(my_arg, handle_exceptions):
try:
do_something(my_arg);
except (handle_exceptions and Exception), e:
print "my_func is handling the exception";
Works without the parentheses, actually, but as long as we're being obfuscated let's not confuse people with little known rules like precedence for except statements.
Upvotes: 4
Reputation: 39990
You can use:
def my_func(my_arg, handle_exceptions):
try:
do_something(my_arg);
except Exception as e:
if not handle_exceptions: raise
print "my_func is handling the exception";
Upvotes: 5