Expect the unexpected with Error Handling.

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:

  • The simulate_work function takes a number of rows as input and initializes a counter starting at 0
  • For each row, a random number is generated between 0 and 1.
  • If the number is below .1, the error_count is incremented by 1. This should happen 10% of the time. It then returns the number of errors it encountered.
  • The timer_nrows function sets the number of rows and the start time so that we can measure how long it takes.
  • The try-except block attempts to run simulate_work and count errors.
  • If any errors occur, it returns that error.
  • finally, whether or not there was an error we return the end_time which is found by taking away the start_time from the current time and returning the error_count.
  • We then call the function and print the results.

Our error_count is roughly 10% of the total number of rows.

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:

  • Use specific exceptions when possible for more precise error handling.
  • The 'else' clause can be used for code that should run only if no exceptions occur.
  • The 'finally' clause ensures certain code always runs, regardless of exceptions.
  • You can raise your own exceptions to control flow and validate input.

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




要查看或添加评论,请登录

Kasim Ali ??的更多文章

  • Escape the 'freak-off' and become 1 in 8 billion

    Escape the 'freak-off' and become 1 in 8 billion

    1. The Monty Hall Problem: Can You Escape P-Diddy’s Freak-Off? The Monty Hall Problem is a classic probability puzzle…

  • Get Paid and Eat Your Cake Too?

    Get Paid and Eat Your Cake Too?

    In this week's newsletter, I want to address a few things as well as thank you all. This week I received well over…

  • datawithkasim #12

    datawithkasim #12

    This week's edition is all about A/B testing, hypothesis tests, derivatives and limits. This week’s datawithkasim…

  • datawithkasim #11

    datawithkasim #11

    These past two weeks I have had two main thoughts continue to come back to me. How do I level up my coding ability and…

  • Essential Math: Types of Numbers

    Essential Math: Types of Numbers

    I have been studying math at the Open university for quite some time now and I had my reservations about studying at an…

  • Plotting and Visualisation: Matplotlib Basics

    Plotting and Visualisation: Matplotlib Basics

    I don’t know about you but I have been using the same types of plots in the past few months. I thought that this would…

    2 条评论
  • Mastering Data Types

    Mastering Data Types

    You might be thinking that I couldn't have picked a more boring subject that data types to write about. I am inclined…

  • qualfications != skill

    qualfications != skill

    When I began my Data Science journey in 2022, I was teaching English, Math, and Science in South Korea. My students…

  • Unlocking the Data Science Path: My Journey and Your Roadmap

    Unlocking the Data Science Path: My Journey and Your Roadmap

    I have noticed that my posts specifically related to Data Science get several times the impression that my other posts…

    2 条评论
  • Fixing your environment.

    Fixing your environment.

    If you are here because you read my previous newsletter on building a guided ML project. There are a few things you…

社区洞察

其他会员也浏览了