Weird Try-Except-Else-Finally behavior with Return statements

PythonTry Except

Python Problem Overview


This is some code that is behaving peculiarly. This is a simplified version of the behavior that I've written. This will still demonstrate the weird behavior and I had some specific questions on why this is occurring.

I'm using Python 2.6.6 on Windows 7.

def demo1():
    try:
        raise RuntimeError,"To Force Issue"
    except:
        return 1
    else:
        return 2
    finally:
        return 3

def demo2():
    try:
        try:
            raise RuntimeError,"To Force Issue"
        except:
            return 1
        else:
            return 2
        finally:
            return 3
    except:
        print 4
    else:
        print 5
    finally:
        print 6

Results:

>>> print demo1()
3
>>> print demo2()
6
3
  • Why is demo one returning 3 instead of 1?
  • Why is demo two printing 6 instead of printing 6 w/ 4 or 5?

Python Solutions


Solution 1 - Python

Because finally statements are guaranteed to be executed (well, presuming no power outage or anything outside of Python's control). This means that before the function can return, it must run the finally block, which returns a different value.

The Python docs state:

> 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.’ > > The return value of a function is determined by the last return statement executed. Since the finally clause always executes, a return statement executed in the finally clause will always be the last one executed:

This means that when you try to return, the finally block is called, returning it's value, rather than the one that you would have had.

Solution 2 - Python

The execution order is:

  1. try block all completes normally -> finally block -> function ends
  2. try block run and get into exception A -> finally block -> function ends
  3. try block make a return value and call return -> finally block -> popup return value -> function ends

So, any return in the finally block will end the steps in advance.

Solution 3 - Python

Note that there has been PEP601 to forbid return statements from finally clauses, but it has been rejected. It has however been added to the style guide in PEP8 that it should be avoided.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKyle OwensView Question on Stackoverflow
Solution 1 - PythonGareth LattyView Answer on Stackoverflow
Solution 2 - PythonFred HuangView Answer on Stackoverflow
Solution 3 - PythonyanlendView Answer on Stackoverflow