Using try, except, else, and finally in Python

Learn how Python exception handling blocks work together so you can catch errors, run code only when no error happens, and always clean up resources.

Quick example

try:
    number = int(input("Enter a number: "))
except ValueError:
    print("Please enter a valid whole number.")
else:
    print("You entered:", number)
finally:
    print("Program finished.")

Use try for risky code, except for handling specific errors, else for success-only code, and finally for cleanup code that must always run.

What this page covers

  • Explain the purpose of try, except, else, and finally
  • Show the order these blocks run
  • Help beginners choose the right block for each task
  • Focus on practical exception handling patterns

What try does

Put code that might fail inside a try block.

Python watches this block for exceptions. An exception is an error that happens while the program is running.

If an error happens inside try:

  • Python stops running the rest of that try block
  • Python looks for a matching except block
  • If it finds one, that handler runs

Example:

try:
    result = 10 / 0
    print("This line will not run.")
except ZeroDivisionError:
    print("You cannot divide by zero.")

Output:

You cannot divide by zero.

Here, 10 / 0 raises a ZeroDivisionError, so Python skips the print() inside try.

If you are new to exceptions, see Python errors and exceptions explained.

What except does

except handles an error that happened in try.

You should catch specific exceptions when possible. This makes your code easier to understand and debug.

Common exception types include:

  • ValueError
  • ZeroDivisionError
  • FileNotFoundError

Example:

try:
    age = int("hello")
except ValueError:
    print("That value cannot be converted to an integer.")

Output:

That value cannot be converted to an integer.

Try to avoid a bare except like this:

try:
    age = int("hello")
except:
    print("Something went wrong.")

This catches almost everything, which can hide useful error details.

A better version is:

try:
    age = int("hello")
except ValueError:
    print("Please enter a valid number.")

If you want more practice with this pattern, see how to use try except blocks in Python.

What else does

else runs only if the try block succeeds.

That means:

  • no exception happened in try
  • Python did not jump to except

Use else for code that should run only after the risky code worked.

Example:

try:
    number = int("42")
except ValueError:
    print("Invalid number")
else:
    print("Conversion worked:", number)

Output:

Conversion worked: 42

Why is this useful?

  • It keeps the try block small
  • It makes debugging easier
  • It clearly separates risky code from success code

Do not use else to handle errors. That is what except is for.

What finally does

finally runs whether an error happens or not.

Use it for cleanup work, such as:

  • closing files
  • releasing resources
  • printing a final message
  • resetting temporary state

Example:

try:
    print("Trying something")
except ValueError:
    print("A value error happened")
finally:
    print("This always runs")

Output:

Trying something
This always runs

In normal Python execution, finally still runs even if there is a return statement in try or except in many cases.

Example:

def test():
    try:
        return "from try"
    finally:
        print("Cleaning up")

print(test())

Output:

Cleaning up
from try

Execution order of the blocks

Python always starts with try.

If no exception happens

The order is:

  1. try
  2. else
  3. finally

Example:

try:
    print("Try block")
except ValueError:
    print("Except block")
else:
    print("Else block")
finally:
    print("Finally block")

Output:

Try block
Else block
Finally block

If a matching exception happens

The order is:

  1. try
  2. except
  3. finally

Example:

try:
    number = int("abc")
except ValueError:
    print("Except block")
else:
    print("Else block")
finally:
    print("Finally block")

Output:

Except block
Finally block

If the exception is not caught

If no matching except block handles the error, finally still runs before the program stops with the error.

try:
    print(10 / 0)
except ValueError:
    print("Wrong type of exception")
finally:
    print("Finally still runs")

Output:

Finally still runs
Traceback (most recent call last):
...
ZeroDivisionError: division by zero

When to use each block

Use each block for one clear purpose:

  • try: risky code
  • except: what to do if it fails
  • else: code to run only on success
  • finally: cleanup that must always happen

A good mental model is:

  • Try it
  • Handle failure
  • Continue on success
  • Clean up at the end

Beginner example with user input

This example converts user input to an integer.

  • int() may fail
  • ValueError is caught if the input is not a valid whole number
  • else runs only when conversion succeeds
  • finally always prints the final message
try:
    number = int(input("Enter a whole number: "))
except ValueError:
    print("Please enter a valid whole number.")
else:
    print("You entered:", number)
finally:
    print("Program finished.")

Possible output if the user enters 25:

Enter a whole number: 25
You entered: 25
Program finished.

Possible output if the user enters hello:

Enter a whole number: hello
Please enter a valid whole number.
Program finished.

If you keep seeing this kind of problem, see ValueError in Python: causes and fixes.

Example with file handling

This example tries to open and read a file.

  • open() may fail if the file does not exist
  • except FileNotFoundError handles that case
  • else runs only when the file was opened successfully
  • finally closes the file if it was opened
file = None

try:
    file = open("message.txt", "r")
    content = file.read()
except FileNotFoundError:
    print("The file was not found.")
else:
    print("File content:")
    print(content)
finally:
    if file is not None:
        file.close()
        print("File closed.")

Why do we set file = None first?

Because if open() fails, the file variable would not be created inside try. Setting it before the try block makes it safe to check in finally.

If you are working with file errors, see FileNotFoundError in Python: causes and fixes.

Best practices

  • Catch the most specific exception you can
  • Keep the try block as small as possible
  • Do not hide errors silently
  • Use finally for cleanup, not normal program logic
  • Use else to separate success code from risky code

Good example:

try:
    number = int(user_input)
except ValueError:
    print("Invalid input")
else:
    print("Valid number:", number)

This is better than putting everything inside try, because it is clearer which line might fail.

You can learn more patterns in how to handle exceptions in Python.

Common beginner mistakes

Putting too much code inside try

Bad:

try:
    number = int(user_input)
    print("Number entered")
    total = number * 10
    print("Total:", total)
except ValueError:
    print("Invalid input")

Better:

try:
    number = int(user_input)
except ValueError:
    print("Invalid input")
else:
    print("Number entered")
    total = number * 10
    print("Total:", total)

This makes it clearer that only the conversion is risky.

Using except without naming an exception type

This can catch unexpected errors and make debugging harder.

Prefer:

except ValueError:

instead of:

except:

Confusing else with except

Remember:

  • except runs when an error happens
  • else runs when no error happens

Using finally when cleanup is not needed

You do not have to use finally every time. Use it when something must always happen at the end.

Catching errors but not fixing the real cause

This is not very helpful:

try:
    number = int(text)
except ValueError:
    pass

It hides the problem.

At minimum, print a useful message or handle the input another way.

Common causes of confusion

These are common reasons beginners struggle with exception blocks:

  • Using try around a large block of unrelated code
  • Catching Exception or using bare except too early in learning
  • Putting code that can also fail inside except without another plan
  • Trying to use a variable in finally that was never created in try
  • Forgetting that else runs only when no exception occurs

Useful debugging commands

These commands can help when you are learning exception handling:

python your_script.py
print(type(value))
print(repr(value))
help(ValueError)
help(FileNotFoundError)

These are useful because:

  • python your_script.py runs your program from the terminal
  • type() shows what kind of value you have
  • repr() shows a more exact version of a value
  • help() shows built-in documentation for an exception type

FAQ

Do I need to use all four blocks every time?

No. You can use only the blocks you need. Many programs use just try and except.

What is the difference between except and else?

except runs when an error happens. else runs when no error happens.

Does finally always run?

In normal Python execution, yes. It is meant for cleanup code that should always run.

Should I use bare except?

Usually no. It can hide useful error details and make debugging harder.

Can I have more than one except block?

Yes. You can catch different exception types with separate except blocks.

Example:

try:
    value = int(input("Enter a number: "))
    result = 10 / value
except ValueError:
    print("That was not a valid integer.")
except ZeroDivisionError:
    print("You cannot divide by zero.")
else:
    print("Result:", result)
finally:
    print("Done.")

See also