3

I have two questions on exception handling.

Q1) I am slightly unsure as to when exactly the operations within else will be carried out in exception handling. I am unsure when the else block would be executed, which doesn't occur in the code below:

def attempt_float(SecPrice,diffprice):
    try:
        return float(SecPrice)
    except:
        return diffprice
    else: 
        print "Did we succeed?"

print attempt_float('7','3') 

Q2) When I run the code below:

def attempt_float(SecPrice,diffprice):
    try:
        return float(SecPrice)
    except:
        return diffprice
    else: 
        print "Did we succeed?"
    finally:
        print "Yasdsdsa"

print attempt_float('7','3')

I am unclear as to why the output is:

Yasdsdsa
7.0
user131983
  • 3,787
  • 4
  • 27
  • 42

2 Answers2

2

In the first case, you return within try, so you never hit the else statement.

In the second one, the finally is executed regardless of how try is exited. From the python docs:

A finally clause is always executed before leaving the try statement, whether an exception has occurred or not. (...) The finally clause is also executed “on the way out” when any other clause of the try statement is left via a break, continue or return statement.

Here is a good example of the order of execution:

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print "division by zero!"
...     else:
...         print "result is", result
...     finally:
...         print "executing finally clause"
...
>>> divide(2, 1)
result is 2
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause

Be sure to read the docs on exceptions!

nchen24
  • 502
  • 2
  • 9
  • Thanks. If the `finally` only executes "on the way out" why is the output in this order: `Yasdsdsa 7.0` rather than the other way around. – user131983 Dec 10 '14 at 01:41
  • 1
    Because you are printing the returned value from `attempt_float`, but before it returns, the `finally` block is executed. – nchen24 Dec 10 '14 at 02:46
2

When Python encounters a return-statement inside a function, it immediately returns (exits) from the function. This means that when you do:

try:
    return float(SecPrice)
...
else: 
    print "Did we succeed?"

"Did we succeed?" will never be printed because you returned in the try: block, thereby skipping the execution of the else: block.


Your second code piece is different however because you used a finally: block. Code inside a finally: block is always executed, no matter if an exception is raised, you return from a function, etc. This is to ensure that any cleanup code which is important (i.e. frees resources) is always executed and not accidentally skipped.

You can read about this behavior in the docs both here:

When return passes control out of a try statement with a finally clause, that finally clause is executed before really leaving the function.

as well as here:

When a return, break or continue statement is executed in the try suite of a try...finally statement, the finally clause is also executed "on the way out."


As for why the output is:

Yasdsdsa
7.0

and not:

7.0
Yasdsdsa

the answer is that the print "Yasdsdsa" line is executed in the finally: block before Python is able to print 7.0 (the return value of attempt_float). Put simply, the execution path for Python is:

  1. Return float(SecPrice).
  2. Run the finally: block.
  3. Resume normal execution with the print attempt_float('7','3') line and print 7.0.
  • Thanks. I'm mainly confused as to why the output is in this order: `Yasdsdsa 7.0` rather than the other way around. – user131983 Dec 10 '14 at 01:40