I found the following behavior at least weird:
def errors():
try:
ErrorErrorError
finally:
return 10
print errors()
# prints: 10
# It should raise: NameError: name 'ErrorErrorError' is not defined
The exception disappears when you use return
inside a finally
clause. Is that a bug? Is that documented anywhere?
But the real question (and the answer I will mark as correct) is:
What is the python developers' reason to allow that odd behavior?
Is it valid for a function to return exception objects? Absolutely. Here is a short list of examples where this may be appropriate: An exception factory.
Upon determining that a catch block cannot sufficiently handle an exception, the exception should be rethrown using an empty throw statement. Regardless of whether you're rethrowing the same exception or wrapping an exception, the general guideline is to avoid exception reporting or logging lower in the call stack.
An exception caught by one catch can be rethrown so that it can be caught by an outer catch. To rethrow an exception, you simply specify throw, without specifying an expression.
A throw statement can be used in a catch block to re-throw the exception that is caught by the catch statement. The following example extracts source information from an IOException exception, and then throws the exception to the parent method. You can catch one exception and throw a different exception.
The exception disappears when you use
return
inside afinally
clause. .. Is that documented anywhere?
It is:
If finally is present, it specifies a ‘cleanup’ handler. The try clause is executed, including any except and else clauses. If an exception occurs in any of the clauses and is not handled, the exception is temporarily saved. The finally clause is executed. If there is a saved exception, it is re-raised at the end of the finally clause. If the finally clause raises another exception or executes a return or break statement, the saved exception is lost.
You asked about the Python developers' reasoning. I can't speak for them, but no other behavior makes sense. A function can either return a value, or it can raise an exception; it can't do both. The purpose of a "finally" clause is to provide cleanup code that is "guaranteed" to be run, regardless of exceptions. By putting a return statement in a finally clause, you have declared that you want to return a value, no matter what, regardless of exceptions. If Python behaved as you are asking and raised the exception, it would be breaking the contract of the "finally" clause (because it would fail to return the value you told it to return).
Here is an interesting comparison for return in finally block, among - Java/C#/Python/JavaScript: (archive link)
Return From Finally
Just today I was helping with some bug in Java and came across interesting problem - what happens if you use return within try/catch statement? Should the finally section fire up or not? I simplified the problem to following code snippet:
What does the following code print out?
class ReturnFromFinally { public static int a() { try { return 1; } catch (Exception e) {} finally{ return 2; } } public static void main(String[] args) { System.out.println(a()); } }
My initial guess would be, that it should print out
1
, I'm callingreturn
, so I assume, one will be returned. However, it is not the case:I understand the logic, finally section has to be executed, but somehow I feel uneasy about this. Let's see what C# does in this case:
class ReturnFromFinally { public static int a() { try { return 1; } catch (System.Exception e) {} finally { return 2; } } public static void Main(string[] args) { System.Console.WriteLine(a()); } }
I prefer much rather this behavior, control flow cannot be messed with in finally clause, so it prevents us from shooting ourself in the foot. Just for the sake of completeness, let's check what other languages do.
Python:
def a(): try: return 1 finally: return 2 print a()
JavaScript:
<script> function ReturnFromFinally() { try { return 1; } catch (e) { } finally { return 2; } } </script> <a onclick="alert(ReturnFromFinally());">Click here</a>
There is no finally clause in C++ and PHP, so I can't try out the last two languages I have compiler/interpreter for.
Our little experiment nicely showed, that C# has the nicest approach to this problem, but I was quite surprised to learn, that all the other languages handle the problem the same way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With