Expect the unexpected with Error Handling.
I wish I had known about error handling when I wrote my first text-based dungeon crawler. It would have made taking the right type of input easy and I would not need to add descriptions to encourage the user to use numbers or letters.
Luckily, you can skip the queue and find out how to use error handling today so you can level up your code.
When should I use error handling?
You use error handling when you expect an error or repeatedly encounter the same error. For example, if you keep getting 'ZeroDivisionError' because you are trying to divide by 0 you can use error handling to deal with this in a consistent way.
def divide(a, b):
try:
return a / b
except ZeroDivisionError:
return 'Cannot divide by 0'
divide(1, 0) #returns 'Cannot divide by 0'
divide(11, 5) #returns 2.2
This is just one of many use cases for using error handling.
How do I write my own 'try' and 'except' block?
try:
# Code that might raise an exception
except:
# Code to handle the exception
You might already know what exception will be raised before writing your code. In this case, you can get to writing your code.
If you do not know what exception will be raised, just run your code and you will soon find out.
In the basic structure above I used a very general 'except' statement but it is better to use specific exceptions like so:
try:
# Code that might raise an exception
except ValueError:
# Handle ValueError
except TypeError:
# Handle TypeError
There are two except blocks here which is perfectly fine. You can add as many as you want so you can deal with different types of errors accordingly.
It is important to note that there is no set way to deal with a specific exception. This is highly dependant on what you are trying to achieve and what the product you are working on needs to do.
What on earth is {e}?
You will commonly see {e} in f-strings.
Here is an example:
try:
# Code that might raise an exception
except ValueError as e:
print(f"Caught a ValueError: {e}")
This will now print the f-string with the value error being stored as a variable and printed in our f-string.
You might think that this code looks similar to an if-else conditional statement.
You are right! They are very similar and in fact we can use an 'else' block inside of our code to denote that 'no problems have occured' and to execute the code as expected.
Here is an example:
try:
number = int(input("Enter a number: "))
except ValueError:
print("That's not a valid number!")
else:
print(f"You entered {number}")
This code prompts the user to enter a number. If the number is in fact, not a number, a value error is raised.
If the code is a number, the else statement runs and we are met with a printed statement returning our input.
领英推荐
'finally' runs no matter what.
You can also use 'finally' in your code to 'do this no matter what'. It always runs whether there was an error or not.
Imagine you have a piece of code that runs across several thousand rows and you want to know how long it took to run, as well as how many ValueErrors it encountered.
This would be a great time to use 'finally':
import random
import time
def simulate_work(rows):
error_count = 0
for _ in range(rows):
if random.random() < 0.1:
error_count += 1
return error_count
def timer_nrows():
rows = 10000
start_time = time.time()
try:
error_count = simulate_work(rows)
except Exception as e:
return e
finally:
end_time = time.time() - start_time
return end_time, error_count
# Call the function and print the results
execution_time, errors = timer_nrows()
print(f"Execution time: {execution_time:.4f} seconds")
print(f"Errors: {errors}")
Lets go through this step by step:
Raising our own errors
Sometimes it can be useful to raise your own errors so you can decide how to handle them. An example of this is when you want to check if a user is at least 18 years old before being allowed to do something on your website or app.
def verify_age(age):
if age < 0:
raise ValueError("Age cannot be negative")
elif age < 18:
raise ValueError("Must be at least 18 years old")
else:
print("Age verified successfully")
# Example usage:
try:
age = input("Enter your age: ")
verify_age(int(age))
except ValueError as e:
print(f"Error: {e}")
This code assigns user input to the variable called age.
This variable is then passed when we call the function and we are met with 1 of 3 messages depending on the input.
We could even add another exception for users who might try typing their name out with letters.
As you can see the 'raise' code blocks are wrapped inside conditional statements and just like before when we used multiple 'except' blocks. We can use several conditional statements to catch a variety of exceptions.
Conclusion
Error handling is a crucial skill for any Python programmer.
As you have seen, using try-except blocks allows you to gracefully handle exceptions, making your code more robust and user-friendly.
Remember these key points:
By incorporating these techniques into your code, you'll create more reliable and maintainable programs and be able to handle all manner of errors.
If you would like to learn more about Python, consider subscribing to my newsletter. I will be releasing a 100% free Python Mastery for Data Scientists course