Python try and except

In the last lesson you learned Introduction to Exceptions. You saw that when something goes wrong, Python raises an exception and your program stops right there. Now the question is simple. What do you do about it? This is where try and except come in. They let you catch that error and keep going instead of crashing.

πŸ€” Why try and except?

Here is the pain. You ask the user to type a number. They type β€œhello” instead. Your program tries to turn that into a number. It fails. It crashes with an ugly error message. The user just sees a long red error message. Then they give up and leave.

The fix is simple. You wrap the risky line in a try block. If it fails, the except block runs instead. Now you can handle the problem nicely. The program keeps running.

🧩 What try and except actually do

Think of it like crossing a busy road. You try to cross. If a car comes, you have a plan ready. You step back onto the footpath. You do not just freeze in the middle of the road.

The try block holds the code that might fail. The except block holds your backup plan. Here is how they fit together:

  • The try block runs first.
  • If nothing goes wrong, the except block is skipped completely.
  • If something goes wrong, Python jumps straight to the except block.

So the except block is not part of the normal flow. It only runs when there is trouble.

✍️ The syntax

Here is the basic shape. The risky code goes inside try. The recovery code goes inside the except block.

try:
# code that might fail
risky_thing()
except:
# code that runs only if it failed
print("Something went wrong.")

Both blocks are indented, just like the body of an if or a loop. The word except lines up with try at the same level.

πŸ§ͺ A simple example

Let us start with a classic mistake. We will divide by zero. Python does not allow it, so it raises an error. Watch how try catches it.

try:
result = 10 / 0
print(result)
except:
print("You cannot divide by zero.")
print("The program keeps running.")

Let us walk through what happens:

  • Python runs 10 / 0 inside the try.
  • That fails, so the print(result) line never runs.
  • Python jumps to the except block and prints the friendly message.
  • Then the last line runs as normal, because we did not crash.

This is what you see:

Output

You cannot divide by zero.
The program keeps running.

See that last line? Without try and except, the program would have crashed before reaching it.

🎯 The real example: catching bad user input

Now the real reason most people learn this. You ask for a number. The user might type letters. The int() function turns text into a whole number. But it only works if the text actually looks like a number. If it does not, int() raises a ValueError.

First, here is the broken version without protection:

age = int(input("Enter your age: "))
print(f"Next year you will be {age + 1}.")

If the user types twenty, here is the mess they get:

Output

Enter your age: twenty
Traceback (most recent call last):
File "main.py", line 1, in <module>
age = int(input("Enter your age: "))
ValueError: invalid literal for int() with base 10: 'twenty'

That traceback is scary, and the program has stopped. Now let us wrap it in try and except.

try:
age = int(input("Enter your age: "))
print(f"Next year you will be {age + 1}.")
except:
print("That was not a valid number. Please type digits like 25.")
print("Thanks for using the program.")

If the user types twenty this time, the program keeps running without crashing:

Output

Enter your age: twenty
That was not a valid number. Please type digits like 25.
Thanks for using the program.

And if the user types a real number like 25, the except block is skipped and everything works:

Output

Enter your age: 25
Next year you will be 26.
Thanks for using the program.

Same code, two different paths. That is the whole point of try and except.

🏷️ Catching a specific exception by name

So far our except catches anything that goes wrong. That can hide problems you did not expect. A bare except will also catch bugs you did not plan for. That makes those bugs harder to find later.

The better habit is to name the exact error you are expecting. For bad input from int(), that error is ValueError. You write it right after the except keyword.

try:
age = int(input("Enter your age: "))
print(f"Next year you will be {age + 1}.")
except ValueError:
print("That was not a valid number. Please type digits like 25.")

Here is the difference:

  • except ValueError: only catches a ValueError. That is the error from typing letters where a number belongs.
  • Any other kind of error is not caught here, so it still shows up. That is good, because you want to know about errors you did not plan for.

Naming the exception makes your intent clear. You are saying, β€œI expect bad input, and here is my plan for it.” You are not silently swallowing every possible problem.

Tip

You can read the name ValueError as β€œthe value had the wrong form.” Each built-in exception has a name that hints at what went wrong, like ZeroDivisionError, TypeError, or FileNotFoundError. Catching the right name is how you handle the right problem.

⚠️ Common Mistakes

A few traps catch people early on. Here is what to watch for.

  • Forgetting the colon or the indentation. Both try: and except: need a colon, and the code under each must be indented.
# ❌ Avoid: no colon, no indentation
try
risky_thing()
except
print("failed")
# βœ… Good: colons and indentation in place
try:
risky_thing()
except:
print("failed")
  • Putting too much code inside one try. If you wrap a huge block, you will not know which line actually failed. Keep the try around just the risky part.
# ❌ Avoid: the try covers safe code too
try:
name = "Alex"
greeting = f"Hi {name}"
age = int(input("Age: "))
except ValueError:
print("Bad number.")
# βœ… Good: only the risky line is inside try
name = "Alex"
greeting = f"Hi {name}"
try:
age = int(input("Age: "))
except ValueError:
print("Bad number.")
  • Using a bare except everywhere. It hides real bugs. Name the exception you expect instead.

βœ… Best Practices

These small habits will save you trouble.

  • Catch the specific exception by name, like except ValueError:, not a bare except:.
  • Keep the try block small, around only the line that might fail.
  • Write a clear, friendly message in the except block so the user knows what to do next.
  • Do not use try and except to hide bugs you should actually fix. It is for problems you expect, like bad input.

🧩 What You’ve Learned

  • βœ… The try block holds code that might fail, and the except block holds your backup plan.
  • βœ… If the try code works, the except block is skipped. If it fails, Python jumps to except.
  • βœ… This stops your program from crashing on errors like bad user input.
  • βœ… Typing letters where int() expects a number raises a ValueError.
  • βœ… Naming the exception with except ValueError: catches only that error and lets real bugs surface.

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    When does the code inside an except block run?

    Why: The except block runs only if something in the try block fails; otherwise it is skipped.

  2. 2

    What error does int('hello') raise?

    Why: int() raises a ValueError when the text does not look like a valid whole number.

  3. 3

    Why is 'except ValueError:' better than a bare 'except:'?

    Why: Naming the exception catches just the expected problem, so unexpected bugs are not hidden.

  4. 4

    What happens to the lines after a try/except block when the try block fails but is caught?

    Why: Once except handles the error, the program continues normally with the lines that follow.

πŸš€ What’s Next?

Right now you can catch one kind of error. But what if a block of code could fail in a few different ways, each needing its own response? That is exactly what we tackle next.

Multiple Exceptions

Share & Connect