try and except blocks
We can handle exceptions using the try..except statement. We basically put our usual statements within the try-block and put all our error handlers in the except-block.
What try and except blocks do
Imagine you are writing code that reads a number from a user. If the user types something that is not a number, Python will raise an exception and your program will crash. With try and except blocks, you can catch that exception and handle it gracefully—perhaps by asking the user to try again instead of letting the program fail.
A try and except block is a way to write code that anticipates potential errors and responds to them. You put statements that might cause an exception inside a try block. If an exception occurs, Python stops executing the rest of the try block and jumps to an except block, where you write code to handle that specific error. If no exception occurs, the except block is skipped entirely and execution continues normally.
The structure of try and except
A try and except block has a specific structure. The try keyword introduces a block of code that might raise an exception. The except keyword introduces a block of code that runs only if an exception occurs. At least one except clause must be paired with every try clause—otherwise there is no point in having the try block.
Execution flow: normal vs. exception
Understanding what happens when code runs is the key to using try and except effectively. There are two paths execution can take: the normal path, where no exception occurs, and the exception path, where an exception is raised and caught.
When an exception occurs inside the try block, Python immediately stops executing the rest of the try block and jumps to the matching except block. Any statements in the try block after the line that raised the exception are skipped.
A worked example: reading an integer
Converting user input to an integer
Write code that asks a user for their age and converts it to an integer. If the user enters something that is not a number, handle the error gracefully.
Identify the risky operation: The int() function will raise a ValueError if the user enters text that cannot be converted to a number. This is the operation that goes inside the try block.
Write the try block: Put the input and conversion inside try: age_str = input('Enter your age: ') and age = int(age_str). These statements might raise an exception.
Write the except block: Catch the ValueError and respond with a helpful message: except ValueError: print('Please enter a valid number'). This runs only if int() fails.
Test both paths: If the user enters '25', the try block succeeds and age is set to 25. If the user enters 'hello', the except block runs and prints the error message.
The program handles both valid and invalid input without crashing.
Catching specific exceptions
When you write an except clause, you can specify which type of exception to catch. The except clause can handle a single specified error or exception, or a parenthesized list of errors and exceptions. If no names of errors or exceptions are supplied, the except block will handle all errors and exceptions.
Catching a specific exception type is better practice than catching all exceptions. When you catch only the exceptions you expect, you avoid hiding bugs in your code that you did not anticipate.
Multiple except blocks and exception matching
You can write multiple except blocks after a single try block. Each except block can handle a different type of exception. When an exception occurs, Python checks each except clause in order and runs the first one that matches the exception type.
In this example, if the user enters 'abc' for the numerator, a ValueError is raised and the first except block runs. If the user enters 0 for the denominator, a ZeroDivisionError is raised and the second except block runs. Python checks the except clauses in order and runs the first one that matches.
The else clause
You can also have an else clause associated with a try and except block. The else clause is executed if no exception occurs in the try block. This is useful when you want to run code only if the risky operation succeeded.
If the user enters a valid number, the try block succeeds and the else clause prints the age. If the user enters invalid input, the except block runs and the else clause is skipped. The else clause is optional and is only executed when no exception occurs.
Common mistakes with try and except
Forgetting to specify which exception to catch
Catching all exceptions hides bugs and makes debugging harder. You might catch exceptions you did not expect or intend to handle.
Fix:
Specify the exception type: except ValueError: print('Invalid input')Putting code that should not be in the try block inside it
Only the int() call can raise a ValueError. The arithmetic operations cannot. This makes it harder to understand which line caused the exception.
Fix:
Move only the risky operation into the try block: try: x = int(user_input) except ValueError: print('Invalid') y = x + 5 z = y * 2Writing a try block without any except clause
A try block must have at least one except clause. Otherwise, there is no point in having the try block.
Fix:
Add at least one except clause: try: x = int(user_input) except ValueError: print('Invalid')Assuming the except block runs when no exception occurs
The except block only runs if an exception is raised. If the try block succeeds, the except block is skipped.
Fix:
Use an else clause if you want code to run when no exception occurs: try: x = 5 except: print('Error') else: print('Success')
When to use try and except
Use try and except blocks when you are performing an operation that might fail in a way you can recover from. Common examples include reading user input, opening files, making network requests, or converting data types. Use try and except to handle the error gracefully and keep your program running.
- Use try and except when you anticipate a specific type of failure
- Catch only the exceptions you expect and know how to handle
- Keep the try block focused on the risky operation
- Write a helpful error message in the except block so the user understands what went wrong
- Use an else clause to run code that should only execute if no exception occurs
- Avoid catching all exceptions with a bare except clause
Practice: building a number validator
Write a program that repeatedly asks a user for a number between 1 and 10 until they enter a valid number. Use a try and except block to catch ValueError when the user enters something that is not a number. Use a separate check to ensure the number is between 1 and 10.
Hints
- Use a while loop to keep asking until valid input is received
- Use try and except to catch ValueError from int()
- After the try and except block, check if the number is in the valid range
- Use a break statement to exit the loop when valid input is received
Summary
A try and except block is a fundamental tool for handling exceptions in Python. The try block contains code that might raise an exception, and the except block contains code that runs if an exception occurs. You can specify which type of exception to catch, write multiple except blocks to handle different exceptions, and use an else clause to run code when no exception occurs. Understanding how to use try and except blocks lets you write programs that respond gracefully to errors instead of crashing.
Key Takeaways
- A try block contains code that might raise an exception; an except block contains code that runs if an exception occurs.
- When an exception is raised inside a try block, Python immediately jumps to the matching except block and skips the rest of the try block.
- You can specify which exception type to catch, write multiple except blocks for different exceptions, and use an else clause to run code when no exception occurs.
- Catch only the specific exceptions you expect and know how to handle; avoid bare except clauses that catch all exceptions.
- Use try and except when performing operations that might fail in a recoverable way, such as reading user input or converting data types.