Purpose of else and finally in exception handling
Asked Answered
S

6

84

Are the else and finally sections of exception handling redundant? For example, is there any difference between the following two code snippets?

try:
    foo = open("foo.txt")
except IOError:
    print("error")
else:
    print(foo.read())
finally:
    print("finished")

and

try:
    foo = open("foo.txt")
    print(foo.read())
except IOError:
    print("error")
print("finished")

More generally, can't the contents of else always be moved into the try, and can't the contents of finally just be moved outside the try/catch block? If so, what is the purpose of else and finally? Is it just to enhance readability?

Suchlike answered 18/5, 2011 at 22:53 Comment(1)
S
76

finally is executed regardless of whether the statements in the try block fail or succeed. else is executed only if the statements in the try block don't raise an exception.

Subirrigate answered 18/5, 2011 at 22:55 Comment(4)
wow, this was so much easier to understand, thank you Sire! :)Jaunita
What is the use of finally then? We can get "finally" printed outside of this try-except block also. Not able to understand the difference it will createFossil
@Fossil the finally will always be executed, whereas if you just add something outside the block it means if the exception causes your program to stop whatever is after the block will not be done.Adeleadelheid
finally will always execute, even if you have a return statement in the "try" block. It will execute the code in "finally" before returning.Doralia
F
15

If you move the contents of the else block inside the try block, you will also catch exceptions that might happen during the else block. If the line

print(foo.read())

in your example throws an IOError, your first code snippet won't catch that error, while your second snippet will. You try to keep try blocks as small as possible generally to really only catch the exceptions you want to catch.

The finally block gets always executed, no matter what. If for example the try block contains a return statement, a finally block will still be executed, while any code beneath the whole try/except block won't.

Fretful answered 18/5, 2011 at 22:58 Comment(0)
N
14

No matter what happens, the block in the finally always gets executed. Even if an exception wasn't handled or the exception handlers themselves generate new exceptions.

Nitty answered 18/5, 2011 at 22:56 Comment(0)
S
11
try:
   print("I may raise an exception!")
except:
   print("I will be called only if exception occur!")
else:
   print("I will be called only if exception didn't occur!")
finally:
   print("I will be called always!")
Salami answered 20/5, 2020 at 15:51 Comment(0)
B
0

finally block always executed

Else block executed If there is not any exception.

I prefer to put the code in finally block which is always executed after try and except blocks.

I prefer to put the code in else block which is executed if the try clause does not raise an exception same like this

Finally

try:
  f = open("file.txt")
  f.write("change file")
except:
  print("wrong")
finally:
  f.close()

Else

try:
   f = open("file.txt")
   f.write("change file")
except:
  print("wrong")
else:
  print("log => there is not any exception")
finally:
    f.close()
Brooklynese answered 4/11, 2020 at 14:6 Comment(0)
M
0

There are 3 possible "states": never occurred, handled and unhandled. You can map the control flow of the try-catch-else-finally clause into these 3 states like that:

from traceback import print_last

e_state = 'unhandled exception'
try:
    # cause an exception here [or don't]
except SomeException as e: # use a suitable [or not] exception type here
    e_state = 'handled exception'
    print('in "except"')
else:
    e_state = 'no exception'
    print('in "else"')
finally:
    print(f'in "finally". {e_state} occurred')
    if e_state == 'handled exception':
        print_last() # since the exception was caught - explicitly inform about it

Full examples below:

1. Handled Exception

from traceback import print_last

e_state = 'unhandled exception'
try:
    1 / 0
except ZeroDivisionError as e:
    e_state = 'handled exception'
    print('in "except"')
else:
    e_state = 'no exception'
    print('in "else"')
finally:
    print(f'in "finally". {e_state} occurred')
    if e_state == 'handled exception':
        print_last()

Output:

in "except"
in "finally". handled exception occurred

Traceback (most recent call last):
  File "...IPython/core/interactiveshell.py", line 3251, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File ".../T/ipykernel_59815/1316012763.py", line 5, in <module>
    1 / 0
ZeroDivisionError: division by zero

2. Unhandled Exception

from traceback import print_last

e_state = 'unhandled exception'
try:
    1 / 0
except KeyError as e:
    e_state = 'handled exception'
    print('in "except"')
else:
    e_state = 'no exception'
    print('in "else"')
finally:
    print(f'in "finally". {e_state} occurred')
    if e_state == 'handled exception':
        print_last()

Output:

in "finally". unhandled exception occurred

---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
Input In [14], in <module>
      3 e_state = 'unhandled exception'
      4 try:
----> 5     1 / 0
      6 except KeyError as e:
      7     e_state = 'handled exception'

ZeroDivisionError: division by zero

3. No Exception

from traceback import print_last

e_state = 'unhandled exception'
try:
    1 / 2
except ZeroDivisionError as e:
    e_state = 'handled exception'
    print('in "except"')
else:
    e_state = 'no exception'
    print('in "else"')
finally:
    print(f'in "finally". {e_state} occurred')
    if e_state == 'handled exception':
        print_last()

Output:

in "else"
in "finally". no exception occurred
Martensite answered 25/4, 2022 at 10:44 Comment(2)
very good example indeed, but is there any real purpose for "else" - which can only be served with elseEmpirin
The same result could be achieved by placing your code at the end of the "Try" block, so.. no. But I'd say the "else" is the "official" block for that ("no exception occurred").Martensite

© 2022 - 2024 — McMap. All rights reserved.