0

I'm currently attempting to write the second part of a quiz program, which uses a simple function load_quiz to load a .json file containing the quiz data, and if a file is not found or is empty it will simply return nothing and refuse playing the quiz.

My code is as follows:

def load_quiz():

    quiz = None
    try:
        with open('quiz.json', 'r') as f:
            quiz = json.load(f)
    except (OSError, ValueError):
        print("Quiz file not found/empty! Please load an unemptied quiz .JSON in order to play.")
        return None
    finally:
        if quiz and quiz[playable]:
            play_quiz(f)
        else:
            print("Quiz file invalid! Please load a valid .JSON in order to play.")
            return None

What I'm wondering is if this approach would even work. If the function returns None within the except block, will that still execute whatever is in the finally block, or will the function simply stop there? If not, then how would I go around that?

Is this a viable option?

  • `finally` *always* gets executed, but I think you want `else`. Or just continue the function outside the `try`, as it will end before that in the failing case. – jonrsharpe Dec 13 '15 at 20:53
  • @jonrsharpe That's exactly what I was thinking to do otherwise. If you'd like, you can turn that into an answer? –  Dec 13 '15 at 20:56
  • This is not a good application of `finally`. It should be used when you want the code to run regardless of exception. In your case, you don't want the quiz to run. So, remove the `finally` block and turn `if quiz and quiz[playable]:` into `if quiz[playable]:` ... otherwise, if the file doesn't exist you get both error messages. – tdelaney Dec 13 '15 at 21:25
  • 1
    Possible duplicate of [Weird Try-Except-Else-Finally behavior with Return statements](http://stackoverflow.com/questions/11164144/weird-try-except-else-finally-behavior-with-return-statements) – GingerPlusPlus Dec 13 '15 at 21:33

3 Answers3

1

If you have this function:

def divide(x, y):
    try:
        return x / y
    except ZeroDivisionError:
        return 0
    finally:
        print('always')

The finally will be executed in the case without an exception:

>>> divide(1, 2)
always
0.5

and in the case the exception got raised and caught:

>>> divide(1, 0)
always
0

As you can see, the always is printed before the return of the function, even though visually the return comes before the finally.

Mike Müller
  • 82,630
  • 20
  • 166
  • 161
1

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.

https://docs.python.org/3.5/tutorial/errors.html#defining-clean-up-actions

GingerPlusPlus
  • 5,336
  • 1
  • 29
  • 52
0

The finally block still gets executed. In fact, it gets executed before the return statement in the except block is executed. Hence you will get a None value returned from the finally block not from the except block.

Yashu Seth
  • 935
  • 4
  • 9
  • 24