Search code examples
pythonerror-handlingtry-catch-finally

Python Error Handling: finally vs. new line dedented


When using try and except for error handling, does it matter whether you explicitly call finally or if you simply go to a new line that is dedented from the exception code? For example, is there any circumstance under which the two functions below will produce different results?

#Function 1 with finally
def final(x):
    try:
        print(x*x)

    except:
        print("Error")

    finally:
        print("End Function")


#Function 2 with new line dedent
def dedent(x):
    try:
        print(x*x)

    except:
        print("Error")

    print("End Function")

Update: Thanks for the explanation of finally running even if there is an error in the except block. One additional thing I wanted to point out is that the finally block will run even if you return an object within the except block. For example, function 3 below will print even after the return while function 4 will not.

#Function 3 with finally
def final(x):
    try:
        print(x*x)

    except:
        return 3

    finally:
        print("End Function 3")


#Function 4 with new line dedent
def dedent(x):
    try:
        print(x*x)

    except:
        return 3

    print("End Function 4")

test1 = final('test')
test2 = dedent('test')

Solution

  • There is the error in the except block that's been mentioned already:

    def final(x):
        try:
            print(x*x)
    
        except:
            print("Error")
            damnit
    
        finally:
            print("End Function")
    
    def dedent(x):
        try:
            print(x*x)
    
        except:
            print("Error")
            damnit
    
        print("End Function")
    
    try:
        final("a")
    except Exception as e:
        print("There was an error:", e)
    #>>> Error
    #>>> End Function
    #>>> There was an error: global name 'damnit' is not defined
    
    try:
        dedent("a")
    except Exception as e:
        print("There was an error:", e)
    #>>> Error
    #>>> There was an error: global name 'damnit' is not defined
    

    There's also return behaviour:

    def final(x):
        try:
            print(x*x)
    
        except:
            print("Error")
            return "Return inside"
    
        finally:
            print("End Function")
            return "Return outside"
    
    def dedent(x):
        try:
            print(x*x)
    
        except:
            print("Error")
            return "Return inside"
    
        print("End Function")
        return "Return outside"
    
    try:
        final("a")
    except Exception as e:
        print("There was an error:", e)
    #>>> Error
    #>>> End Function
    #>>> 'Return outside'
    
    try:
        dedent("a")
    except Exception as e:
        print("There was an error:", e)
    #>>> Error
    #>>> 'Return inside'