http://docs.python.org/reference/compound_stmts.html#the-try-statement
Answer from wRAR on Stack OverflowThe optional else clause is executed if and when control flows off the end of the try clause.
Currently, control “flows off the end” except in the case of an exception or the execution of a return, continue, or break statement.
http://docs.python.org/reference/compound_stmts.html#the-try-statement
The optional else clause is executed if and when control flows off the end of the try clause.
Currently, control “flows off the end” except in the case of an exception or the execution of a return, continue, or break statement.
The reason for this behaviour is because of the return inside try.
When an exception occurs, both finally and except blocks execute before return. Otherwise only finally executes and else doesn't because the function has already returned.
This works as expected:
def divide(x, y):
print 'entering divide'
result = 0
try:
result = x/y
except:
print 'error'
else:
print 'no error'
finally:
print 'exit'
return result
print divide(1, 1)
print divide(1, 0)
python - Is it correct to use a return statement within a try and except statement? - Stack Overflow
What happens when you use try and except statements in a function that both have a return statement in them BUT you also have a finally statement?
Functions Try Except
Allow `break` and `return` inside `except*` clause - Ideas - Discussions on Python.org
Videos
Keep it simple: no try block
It took me a while to learn, that in Python it is natural, that functions throw exceptions up. I have spent too much effort on handling these problems in the place the problem occurred.
The code can become much simpler and also easier to maintain if you simply let the exception bubble up. This allows for detecting problems on the level, where it is appropriate.
One option is:
try:
return map(float, result)
except ValueError, e:
print "error", e
raise
but this introduces print from within some deep function. The same can be provided by raise which let upper level code to do what is appropriate.
With this context, my preferred solution looks:
return map(float, result)
No need to dance around, do, what is expected to be done, and throw an exception up, if there is a problem.
If you surround the code block containing a return statement with an try/except clause, you should definitely spend some thoughts of what should be returned, if an exception actually occurs:
In you example, the function will simply return None. If it's that what you want, I would suggest to explicitely add a return None like
except ValueError, e:
print "error", e
return None
in your except block to make that fact clear.
Other possibilities would be to return a "default value" (empty map in this case) or to "reraise" the exception using
except ValueError, e:
print "error", e
raise
It depends on how the function is used, under what circumstances you expect exceptions and on your general design which option you want to choose.
Ok, that was an awful title and I'm sorry... but it's hard to phrase! My question overall is, if we use a try statement in a function (and let's imagine it works, we don't end up having to handle any exceptions) and there is a return statement in this try-block. Won't that cause us to leave the function? Since, we are returning control back to main, let's say.
But, we have a finally statement in our function to. It might do something trivial like print something. Does this get executed even though we should have hit return?
Now, I have tested this. And what it seems to do is reach the return statement, ignore it, carry out the finally statement and then go back to the return. But I would like to know if I am understanding this correctly.
Neither of these is more Pythonic than the other. The examples are too trivial to say which is preferrable but it really all depends on how things should work.
Catch and logging/reporting an issue is just a hair's breadth away from squashing exceptions which is almost always a terrible idea. The only reason I can see doing this is that you want whatever the issue is to not stop execution. If you are going to do something like this, it's really crucial to make sure that you return something sensible that works for the caller. If the next thing that happens is that the calling code throws its own exception because e.g., None doesn't have an add method, you are at best just making things harder to troubleshoot. It could be a lot worse, however. A lot of serious bugs are due to returning nulls/None after catching an error. I think there are times that is makes sense to do this, but they are rare in my experience.
Allowing the raw exception to bubble out is the next least-worst option, IMO. This can be fine if you are building something small where it will be easy to find the what the problem is when things crash with a KeyError. In a situation where you are leveraging a lot of duck-typing, passing around function references, or using annotations, it can sometimes be difficult. For example, if you are using this code behind a web endpoint, what HTTP error code should you use when you catch a KeyError. 500 might be the right answer in most cases but there might be times you want to produce something else depending on where the key was not found.
That brings me to the last option which you don't mention: catch and raise a separate, more meaningful error. That allows you to distinguish between say, a KeyError thrown because the request was for something that isn't valid and a KeyError thrown because of a bad configuration.
Neither is pythonic. Pythonic code would be:
my_dict = {}
def fetch_value(key):
return my_dict[key]
val = fetch_value('my_key')
Remember, simple is better than complex and flat is better than nested. Since your except-block does not handle the exception in any meaningful way, it is better to just let it bubble up the call stack and terminate the program.
But in your code the error is ignored and it implicitly returns None if the key is not found. If this is what you want, then it can be done simpler with the get() method:
def fetch_value(key):
return my_dict.get(key)
"Handling" an error by just logging a message and then continuing as if nothing happened, is a terrible antipattern from the Java world which has no place in Python. Exceptions should only be caught if they can be meaningfully handled.