FAQ: Exceptions - The finally Clause

This community-built FAQ covers the “The finally Clause” exercise from the lesson “Exceptions”.

Paths and Courses
This exercise can be found in the following Codecademy content:

Learn Intermediate Python 3

FAQs on the exercise The finally Clause

There are currently no frequently asked questions associated with this exercise – that’s where you come in! You can contribute to this section by offering your own questions, answers, or clarifications on this exercise. Ask or answer a question by clicking reply (reply) below.

If you’ve had an “aha” moment about the concepts, formatting, syntax, or anything else with this exercise, consider sharing those insights! Teaching others and answering their questions is one of the best ways to learn and stay sharp.

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!
You can also find further discussion and get answers to your questions over in Language Help.

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head to Language Help and Tips and Resources. If you are wanting feedback or inspiration for a project, check out Projects.

Looking for motivation to keep learning? Join our wider discussions in Community

Learn more about how to use this guide.

Found a bug? Report it online, or post in Bug Reporting

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

What is different to this code:

import database

instrument = 'Kora'
database.connect_to_database()

try:
  database.display_instrument_info(instrument)
except KeyError:
  print('Oh no! This instrument does not exist.')
else:
  print(instrument)
# Write your code below: 
finally:
  database.disconnect_from_database()

than this:

import database

instrument = 'Kora'
database.connect_to_database()

try:
  database.display_instrument_info(instrument)
except KeyError:
  print('Oh no! This instrument does not exist.')
else:
  print(instrument)
# Write your code below:
database.disconnect_from_database()

Wouldn’t in the second code the last line also run like using finally. Also the second is shorter? Why should we use finally what are the benefits(someone, @toastedpitabread)?

1 Like

Hi,

A finally clause will run no matter what, even if there’s a return statement.
Example:

>>> def fn(x):
...   try:
...     return (5/x)
...   except ZeroDivisionError:
...     return "undefined"
...   finally:
...     print("btw, did you mean to do that?")
... 
>>> fn(0)
btw, did you mean to do that?
'undefined'

So in this case, usually you’d expect the function to return a value and not do anything afterwards, but the finally guarantees a code block will regardless of pre-emptive returns.

Why is this useful? Usually when dealing with volatile objects. Anytime python opens a file it has to gracefully close it as well, lest the file get corrupt. This is especially important when it comes to databases.

Note, my example is slightly misleading because it shows that this code runs because it fails (because of the error). It’s notable that the finally runs even with no error thrown

>>> def fn(x):
...   try:
...     return (5/x)
...   except ZeroDivisionError:
...     return "undefined"
...   finally:
...     print("btw, did you mean to do that?")
... 
>>> fn(1)
btw, did you mean to do that?
5.0

so to fix my own example (and I’m leaving it for posterity to laugh at myself) something more apt would have been

>>> def fn_thatexpectsnumbers(x):
...   try:
...     return 5**x
...   except:
...     return "what was that?"
...   finally:
...     print("you are now executing the function")
... 
>>> fn_thatexpectsnumbers("hello")
you are now executing the function
'what was that?'
>>> fn_thatexpectsnumbers(5)
you are now executing the function
3125
2 Likes

This somewhat confusing:

Wouldn’t the output you are now executing the function output come after ‘what was that’ because of order?

Try running it! :slight_smile: see what happens. (you might need to wrap a print statement on the function call since this was done on a console)

It goes to underline that it’s a special case clause for things that must be run for safety reasons.

The output is just you are now executing the function. But because I didn’t print the function it didn’t print the returned value “what was that?”. But why does the finally run first and the except last. I say the flowmap in this lesson; it had the else and except before the finally.

It’s a safety feature of the clause finally. It’s only meant to be used for very specific things.

Should I not use finally when I don’t need return in try, except and else?

In terms of Python, what is a safety feature?

So finally I believe only exists within try/except patterns (could be wrong on this, check documentation).

You use it when those patterns create a behavior that if not taken care of could be not safe.

One example of safety is with file corruption: every time you open a file with python, you must close it (if not it runs risk of becoming corrupt). Same with databases.

It happens that sometimes you know you might try something that may fail in the middle of having a file or db open, and you need a fail-safe to make sure it closes no matter what.

I’m sure there are more concrete examples out there. So feel free to search around for those!

So finally is executed no matter what(even return) and may sometimes be better than than not using finally because you could exit the try block in a function, never ran the finally and bad things to programs can happen.

  • So finally is executed no matter what(even return ) — yes

  • and may sometimes be better than than not using finally because you could exit the try block in a function, never ran the finally and bad things to programs can happen

this second statement i’m not sure what you mean.

Usually the volatile behavior you try will be in the try block. If there’s no uncertainty, there’s no need for finally. I think you said this but maybe I’m interpreting it wrong.

I mean that a return might exit a function with tryexcept and the finally block wouldn’t run and that might cause trouble.

finally always will run if the code reaches the tryexcept. In fact, (I don’t want to get too technical), if the finally has a return any other return will get ignored.

I recommend documentation and practice. Maybe even look at some examples.

I had the same question when first going through this exercise. What I found that cleared things up for me was seeing how even though the programm ran into an unhandled error (NameError by commenting out the definition of instrument for example), the code in the finally section was still excecuted. That way cleanly disconnecting the database before stopping the programm by throwing the exception.

Example:

import database

#instrument = 'Kora'
database.connect_to_database()

try:
  database.display_instrument_info(instrument)
except KeyError:
  print('Oh no! This instrument does not exist.')
else:
  print(instrument)
# Write your code below: 
finally:
  database.disconnect_from_database()

outputs:

Establishing connection to instrument database server...
Destroying connection to instrument database server...
Traceback (most recent call last):
  File "instrument.py", line 7, in <module>
    database.display_instrument_info(instrument)
NameError: name 'instrument' is not defined
2 Likes

Welcome to the forums/community @toblbg! Here you can ask questions and join the community!

I think this lesson is missing some information. The lesson says

Note that the finally clause can be used independently (without an except or else clause). This is a convenient way to guarantee that a behavior will occur, regardless of whether an exception occurs:

try:   
   check_password()
finally:
   load_footer()    # Other code we always want to run 

But then I tried:

# Prints the equation of the line spanned by 'vector' and containing the 'point' 
def line_equation(vector,point):
    # Case vector[0]=0
    message = "x = {}".format(point[0])
    try:
        slope = vector[1] / vector[0]
        message = "y = {}x + {}".format(slope, point[1]-slope*point[0])
    finally:
        print(message)

line_equation((0,1),(1,1))
 

And got

x = 1


ZeroDivisionError Traceback (most recent call last)
Cell In[1], line 11
8 finally:
9 print(message)
—> 11 line_equation((0,1),(1,1))

Cell In[1], line 6, in line_equation(vector, point)
4 message = “x = {}”.format(point[0])
5 try:
----> 6 slope = vector[1] / vector[0]
7 message = “y = {}x + {}”.format(slope, point[1]-slope*point[0])
8 finally:

ZeroDivisionError: division by zero

From what I got from the text, the code above would run with no warning about the occurence of an exception. That is, just like:

# Prints the equation of the line spanned by 'vector' and containing the 'point' 
def line_equation(vector,point):
    # Case vector[0]=0
    message = "x = {}".format(point[0])
    try:
        slope = vector[1] / vector[0]
        message = "y = {}x + {}".format(slope, point[1]-slope*point[0])
    except:
        pass
    finally:
        print(message)

line_equation((0,1),(1,1))

So I think it would be more accurate to add in the lesson something like: “Still, the finally clause will not prevent the exception warning to be printed.”