Suppose that I am using a library X that specifies for example that exception.BaseError is the base class for all exceptions of X.
Now, there is another exception, say X.FooError, which of course inherits from exception.BaseError but is more generalized, let's say that it handles invalid input. Let's suppose there are many other such classes, inherting from BaseError but all for generalized cases.
X
|
BaseError
|
FooError
So I want to then check for invalid input. So which exception should I catch? Of course, catching each individual exception is not possible, so I catch the X.BaseError and then print an error message. Or I can catch the X.FooError specifically but then I miss out all the other error cases.
Is this the standard way of doing it -- catch the base exception? If yes, then why do the other exceptions exist? For the generalized case when we want to catch a specific exception?
Catch only the exceptions you can handle. If you can handle both the base exception and the derived exception then catch both. But make sure to put the derived exception first, since the first exception handler found that matches is the one used.
try:
X.foo()
except X.FooError:
pass
except X.BaseError:
pass
As usual, there is good advice in PEP-8, Style Guide for Python Code:
When catching exceptions, mention specific exceptions whenever possible instead of using a bare except: clause.
There's lots more in there, but it's pointless me reproducing it here.
In this case, I would catch the specifics, were I to handle them differently to a BaseError and the BaseError for those that require more general handling. I would stop well short of catching the built-in Exception, however.
You catch a specfic exception by defining it in the except clause, thus:
try:
#do stuff
except X.FooError:
# handle the error
except (X.AnotherError, x.YetAnotherError), exc:
print 'I'm handling %s' % exc
Notice you can handle multiple exception classes by listing them in a tuple.
Related
I'm reading the Python Tutorial.
I came across a part that says:
'''
If you need to determine whether an exception was raised but don’t intend to handle it, a simpler form of the raise statement allows you to re-raise the exception:
'''
try:
raise NameError('HiThere')
except NameError:
print('An exception flew by!')
raise
I don't understand why would one raise an exception, handle it and then re-raise it??
If the programmer doesn't want to handle the exception they shouldn't use a try..except statement in the first place??
It helps if you don't think of exceptions as "mistakes" that have to be caught/corrected, and instead think of them as a way of communicating information.
Sometimes when you catch an exception it's expected, or you can find a way around it. Other times, the exception means you can't do the thing you were trying to do, and so you want to raise an exception to your own caller to let them know why it's not going to work out.
When you're in that situation, sometimes you'll catch the lower-level exception that thwarted your plans, and then raise your own exception (maybe with a more specific type) to communicate your own failure to the caller. Sometimes it might work just as well to simply raise the same exception back to the caller. In the situation where you just want the lower level exception to go all the way up to the caller, you might opt to just not catch it, but what if you want to log a message or clean up some piece of internal state before you go down in flames? That's where the except/raise pattern is useful.
begin_complicated_process()
try:
do_risky_thing()
except ShenanigansError:
log("Did someone say shenanigans?!")
unwind_complicated_process()
raise
complete_complicated_process()
I am using an external library which raises a generic Exception in one of it's modules under certain circumstances:
if some_condition:
raise Exception('DSSP failed to produce an output')
This only occurs in a few edge-cases, but is still something I want to catch and handle.
So, other than cursing the original coders for raising a generic Exception, what are my options here? I only want to catch and handle this particular line in the original code. What is the most Pythonic way of dealing with this?
Catch Exception and reraise if it's not the exception you're looking for:
try:
do_thing()
except Exception as e:
if type(e) is not Exception:
# Not what we're looking for. Let it pass.
raise
handle(e)
You can add some other checks if you want to really make sure it's the exception you're looking for, such as examining the exception's message.
I have some code in a Python except clause that is intended to do some logging, but the logging code might itself cause an exception. In my case, I'd like to just ignore any second exception that might occur, and raise the original exception. Here is a very simplified example:
try:
a = this_variable_doesnt_exist
except:
try:
1/0
except:
pass
raise
Running the above code, I hope to get:
NameError: name 'this_variable_doesnt_exist' is not defined
but instead, in Python 2.x, I get:
ZeroDivisionError: integer division or modulo by zero
I've discovered that in Python 3.x, it does what I want.
I couldn't find much commentary on this in the Python 2.x docs (unless I missed it). Can I achieve this in 2.x?
I believe what you're seeing is the result of exception chaining, which is a change in Python 3.
From the Motivation section of the PEP:
During the handling of one exception (exception A), it is possible that another exception (exception B) may occur. In today's Python (version 2.4), if this happens, exception B is propagated outward and exception A is lost. In order to debug the problem, it is useful to know about both exceptions. The __context__ attribute retains this information automatically.
The PEP then goes on to describe the new exception chaining (which is implemented in Py3k) in detail—it's an interesting read. I learned something new today.
With abstraction:
def log_it():
try:
1 / 0
except:
pass
try:
this = that
except:
log_it()
raise
Does what you want in Python 2.5
Another way to do it is to store the exception in a variable, then re-raise it explicitly:
try:
this = that
except NameError, e: # or NameError as e for Python 2.6
try:
1 / 0
except:
pass
raise e
Note that you probably shouldn't just be using a bare except to catch everything that might come - it's usually best to catch the specific exceptions you expect to occur in case a drastic and fatal exception (like being out of memory) occurs.
In my CausedException class I take care of that for Python 2.x (and for Python 3 as well, in case you want to pass cause trees instead of simple cause chains). Maybe it can help you.
Say I have a
class Rocket(object):
def __init__(self):
self.ready = False
def prepare_for_takeoff(self):
self.ready = True
def takeoff(self):
if not self.ready:
raise NotReadyException("not ready!")
print("Liftoff!")
Now, which of the standard exceptions would be most appropriate to derive NotReadyException from? Would it be ValueError, since self has the wrong state/value?
Now, which of the standard exceptions would be most appropriate to derive NotReadyException from?
Exception
Don't mess with anything else.
http://code.google.com/p/soc/wiki/PythonStyleGuide#Exceptions
What are your use cases for exception handling?
If you derived your exception from, say ValueError, would you ever write a handler that used except ValueError: to catch both exceptions and handle them in exactly the same way? Unlikely.
ValueError is a catch-all when more specific exceptions aren't appropriate. Your exception is very specific.
When you have an application-specific exception like this, the odds of it sharing any useful semantics with a built-in exception are low. The odds of actually combining the new one and an existing exception into a single handler are very, very low.
About the only time you'll ever combine an application-specific exception with generic exceptions is to use except Exception: in some catch-all logger.
I'd just derive it from Exception. Programmers who catch ValueError might be quite surprised that they catch your NotReadyException as well.
If you will be defining a lot of similar types of state-related exceptions, and it would be convenient to be able to catch 'em all, you might define a StateError exception and then derive NotReadyException from that.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Does a exception with just a raise have any use?
Is there any value to re-raising an exception with no other code in between?
try:
#code
except Exception:
raise
I was recently looking through some code and saw a few blocks like these with nothing extra in the except block but another raise. I assume this was a mistake and poor decision making, am I right?
I've seen similar code before in a (set of) horrible VB.NET projects. Either the intent was to catch and log exceptions, without ever coming back to finish the logging, or they heard "you must catch exceptions", implemented this functionality, and someone else decided it should just re-raise.
There is no benefit to the above code.
I am not able to come up with something useful, other than to keep it as a placeholder for later insertion to catch useful exceptions.
It kind of avoids re-indenting the code, when you want to include the "try .. except.." blocks later on.
Example built on this question. If there's some other except's in the try block, it can be used to filter the exceptions, but alone it's pointless.
class FruitException(Exception): pass
try:
raise FruitException
except FruitException:
print "we got a bad fruit"
raise
except Exception:
print "not fruit related, irrelevant."
Yes, this is usually a bad practice. The only (somewhat) correct usage I've seen of this pattern was before VB.NET had a Using construct available. Usage looked something like:
Dim myResource As DisposableService
Try
myResource = New DisposableService()
' This might throw an exception....
myResource.DoSomething()
Catch
Throw
Finally
' Perform cleanup on resource
If Not myResource Is Nothing Then
myResource.Dispose()
End If
End Try
Other than that, I really can't think of a good use case for this sort of thing.
sometimes it useful let me give you a real example that i did i my work :
this was is in a decorator that wrap func : so basically what i have wanted is to re-raise the error that i catched when i called the function func so that the decorator don't change the behavior of the function func, because when func raise an exception the exception are send to the GUI so that an error message can pop up to the user,
and for the try except i use it because i want to execute the code in finally even if an exception is raised
try:
result = func(self, *args, **kws)
return result
except Exception, ex:
# If an exception is raised save it also.
logging_data['message'] = str(ex)
logging_data['type'] = 'exception'
# Raise the error catched here so that we could have
# the same behavior as the decorated method.
raise
finally:
# Save logging data in the database
....
hope this will help to understand the use of re-raise
Typically in a try-catch model, any uncaught exception will automatically be thrown (raised?). Catching the exception only to re-throw it may be in the spirit Allman style coding, but serves no functional purpose.
Uh, Imagine
def something(a,b):
try:
// do stuff
except SomethingSpecificToThisFunction:
//handle
except: //Everything else, should likely be handled somewhere else
raise
try:
something("a","b")
except e:
Log(e)
Then again its default behaviour anyways, so might just want to leave it out
There are some approaches with such technics in multithread enviroment. For example to throw something to upper stack level.