Why do we need the "finally" clause in Python?

Viewed 185758

I am not sure why we need finally in try...except...finally statements. In my opinion, this code block

try:
    run_code1()
except TypeError:
    run_code2()
other_code()

is the same with this one using finally:

try:
    run_code1()
except TypeError:
    run_code2()
finally:
    other_code()

Am I missing something?

18 Answers

Here's a peice of code to clarify the difference:

...

try: 
  a/b
  print('In try block')
  
except TypeError:
  print('In except block')
  
finally: 
  print('In finally block')

print('Outside')

a, b = 0, 1

Output:

In try block 
In finally block 
Outside

(No errors, except block skipped.)


a, b = 1, 0

Output:

In finally block

Traceback (most recent call last):
a/b
ZeroDivisionError: division by zero

(No exception handling is specified for ZeroDivisionError and only the finally block is executed.)


a, b = 0, '1'

Output:

In except block 
In finally block 
Outside

(Exception is handled properly and the program is not interrupted.)


Note: If you have an except block to handle all types of errors, the finally block will be superfluous.

Perfect example is as below:

try:
    #x = Hello + 20
    x = 10 + 20 
except:
    print 'I am in except block'
    x = 20 + 30
else:
    print 'I am in else block'
    x += 1
finally:
    print 'Finally x = %s' %(x)

A try block has just one mandatory clause: The try statement. The except, else and finally clauses are optional and based on user preference.

finally: Before Python leaves the try statement, it will run the code in the finally block under any conditions, even if it's ending the program. E.g., if Python ran into an error while running code in the except or else block, the finally block will still be executed before stopping the program.

Try running this code first without a finally block,

1 / 0 causes a divide by zero error.

    try:
        1 / 0    
        print(1)
        
    except Exception as e:
        1 / 0
        print(e)
        

Then try running this code,

    try:
        1 / 0    
        print(1)
        
    except Exception as e:
        1 / 0
        print(e)
   
    finally:
        print('finally')

For the first case you don't have a finally block,
So when an error occurs in the except block the program execution halts and you cannot execute anything after the except block.

But for the second case,
The error occurs but before the program halts python executes the finally block first and then causes the program to halt.
Thats is why you use finally and do stuff that is really important.

Run these Python3 codes to watch the need of finally:

CASE1:

count = 0
while True:
    count += 1
    if count > 3:
        break
    else:
        try:
            x = int(input("Enter your lock number here: "))

            if x == 586:
                print("Your lock has unlocked :)")

                break
            else:
                print("Try again!!")

                continue

        except:
            print("Invalid entry!!")
        finally:
            print("Your Attempts: {}".format(count))

CASE2:

count = 0

while True:
    count += 1
    if count > 3:
        break
    else:
        try:
            x = int(input("Enter your lock number here: "))

            if x == 586:
                print("Your lock has unlocked :)")

                break
            else:
                print("Try again!!")

                continue

        except:
            print("Invalid entry!!")

        print("Your Attempts: {}".format(count))

Try the following inputs each time:

  1. random integers
  2. correct code which is 586(Try this and you will get your answer)
  3. random strings

** At a very early stage of learning Python.

I was trying to run a code where i wanted to read excel sheets. Issue was, if there is a file which has no sheet named say : SheetSum I am not able to move it to error location!! Code i wrote was:

def read_file(data_file):
    # data_file = '\rr\ex.xlsx'
    sheets = {}
    try:
        print("Reading file: "+data_file)
        sheets['df_1'] = pd.read_excel(open(data_file,'rb'), 'SheetSum')
    except Exception as excpt:
        print("Exception occurred", exc_info=True)
    return sheets

read_file(file)
shutil.move( file, dirpath +'\\processed_files')

Giving Error :

[WinError 32] The process cannot access the file because it is being used by another process

I had to add full try except with finally block and tell finally i need to close the file in any case like:

def read_file(data_file):
    # data_file = '\rr\ex.xlsx'
    sheets = {}
    sheets_file = None
    try:
        print("Reading file: "+data_file)
        sheets_file = open(data_file,'rb')
        sheets['df_1'] = pd.read_excel(sheets_file, 'SheetSum')
    except Exception as excpt:
        print("Exception occurred", exc_info=True)
    finally:
        if sheets_file:
            sheets_file.close()
    return sheets

read_file(file)
shutil.move( file, dirpath +'\\processed_files')

Otherwise, file still remains open is the background.

If finally is present, it specifies a cleanup handler. The try clause is executed, including any except and else clauses. If an exception occurs in any of the clauses and is not handled, the exception is temporarily saved. The finally clause is executed. If there is a saved exception it is re-raised at the end of the finally clause. If the finally clause raises another exception, the saved exception is set as the context of the new exception.

..More Here

Just to enable Abhijit Sahu's comment on this answer to be seen much better and with syntax highlighting:

Like this, you can observe what happens with which code block when:

try: 
    x = Hello + 20 
    x = 10 + 20 
except: 
    print 'I am in except block' 
    x = 20 + 30 
else: 
    print 'I am in else block' 
    x += 1 
finally: 
    print 'Finally x = %s' %(x) 

Here you can see how try, except, else, and finally work together. Actually, since your code doesn't have 'else' then what you claimed is right. I.e., There is no difference between the two statements that you wrote. But if 'else' is used somewhere, then 'finally' makes a difference

Related