Clean Python: Try/Except
Tags: python, errors
Published: 2023-06-12 16:39:29

## Exceptional Error Handling in Python 

We code in Python because the language has incredible ease of use.  Error handling in Python is no exception.  Try/except is Python's method of handling potentially hazardous input without crashing your program, and returning to the user important information needed in order for the program to proceed.  In this post, we will discuss three specific instances of when try/except is a great fit for error handling:  

1.  Cushion potentially erroneous code, such as division by 0 or file access to a file that doesn't exist or an unsupported file type.

2. Handle network or server issues that might occur when working with external systems, such as an API endpoint, giving the user workable information to allow the program to function correctly.

3.  Wrap user input to handle unexpected data types which allows the program to continue to function.

This post will primarily focus on the third point, demonstrating how to handle try/except in the context of unexpected or incompatible user input.

A word of caution: while try/except blocks can effectively handle problematic input and prevent crashes, they should be used judiciously as they can potentially mask issues that a developer could otherwise address to improve performance.  

{% embed https://www.youtube.com/watch?v=HdL82tAZR20&t=831s %}

_Please begin the video at 6:04 to hear Dr. Charles Severance, Clinical Professor of Information at the University of Michigan, explain Python's try/except.  This video is part of a larger collection complied by [freeCodeCamp](https://www.freecodecamp.org/learn/scientific-computing-with-python/python-for-everybody/introduction-why-program) to help devs learn more about Python._

--- 

## Cushioning your Program from the Dangers of TypeError

Instead of writing validations on the input code (which we might not have the ability to do for browser or front-end input), we can anticipate when a bad data type might come in.  

In your programing, you have identified a potentially dangerous line of code.  Let's say your program looks like this:

```
x= userInput
calculate = x+5
print(calculate)

#userInput = 5
```
This is a very simple program that calculates the value of adding 5 to the user input.  If userInput = 5 as the comment suggests, then output naturally is 10.  

Now imagine the situation that you are working with a front-end team responsible for writing the user facing functionality.  For some reason, the validations for the front end don't work as anticipated/ aren't written in.  So the user is able to enter input as this:

```
#userInput = 'five'
```

Python then attempts to calculate:

```
x = 'five'
calculate = x + 5

#TypeError -- Your Python Program Crashes
```
As Python programers, this is a failure on our part--we did not write in error handling code to keep our program running/ provide valuable feedback to our user in order to allow Python to continue its computing.  This is where we can use try/except.

```
x = userInput

try:
    calculate = int(x) + 5
    return(calculate)
except:
    return("The input was not a valid number. Please try again.")
```
This returns some valuable information to our user.  They now know that in order for the program to work, they need to enter a number.  

## What Is Happening Here?

Python is synchronous by default, meaning it only computes code line by line--it does not "know" what is happening next.  When we write our function inside of a try: statement, it stores in memory something along the lines of : "I am told to carry out the computing of the following block of code.  If it fails, I am not to halt the program and return the error; rather, I am to proceed to the block labeled 'Except:' and execute the code contained within.."  

In this way, if we can anticipate potentially hazardous input (as in our current situation with user input), and we can effectively allow Python to continue running the program, even with bad input.   

If you are familiar with if: else: statements, it will come to no surprise to you that Python does not even hit the return statement in the try: block upon failure; instead, it moves into the Except: block and computes ALL of the code nested there.  

Now the user has been notified of Python's issue in computing data, the program has not crashed, and we have succeeded as Developers by means of effective communication across the stack.  


![Dancing Computer Head](https://media0.giphy.com/media/MT5UUV1d4CXE2A37Dg/200w.gif?cid=6c09b952akmndl5vgpr7t0k7cd9igwsibnc2ivcvefipb8ww&ep=v1_gifs_search&rid=200w.gif&ct=g)


## Wrapping Up: Empowering Your Programs with Exception Handling

As we've seen, Python's try/except mechanism is an essential tool in the programmer's toolbox. It enhances the robustness and reliability of your code, cushioning against potential pitfalls and keeping your program from crashing even when faced with unpredictable inputs or unexpected events.

While this post has specifically delved into handling TypeError exceptions arising from user input, remember that the try/except construct is far more versatile. You can and should use it judiciously to handle a variety of exceptional circumstances.

That being said, it's essential to not fall into the trap of using try/except blocks to mask code inefficiencies or bugs that should be fixed directly. Overusing them can lead to code that's difficult to debug and maintain.n. Always strive to write clean, efficient code and only use exception handling where it's logical and beneficial to do so.

As Dr. Charles Severance rightly emphasizes, Python's error handling, particularly try/except, can make your code more resilient and user-friendly.  In the grand scheme of things, using try/except appropriately means that you're writing code that respects the user's time and experience. It's a demonstration of good coding ethics and the mark of a responsible developer.

## Continue Your Research 

Curious of other ways can you use try/except?  Open up a [Replit environment](https://replit.com/) and practice coding up some simple programs to further your understanding of the try/except environment.  

Here is a code example to try with an unsuccessful api endpoint:

```
import requests

try:
    response = requests.get('https://nonexistent-api.com')
    data = response.json()
except:
    print("Error: Unable to connect to the API endpoint.")
```
 
Here is another quick example of attempting to access a file that doesn't exist:

```
try:
    with open('non_existent_file.txt', 'r') as f:
        content = f.read()
except FileNotFoundError:
    print("Error: The file does not exist.")
```

If you are certain of the error that Python might throw, you can specify the exact error type:

```
try:
    # some code here
except TypeError:
    # handle TypeError
except ValueError:
    # handle ValueError
# and so on...

```

Open up the Replit environment and try modifying the code to see how the program's behavior changes under different circumstances.  


## Let's keep the conversation moving!  

Do you have any additional thoughts on Python error handling, or on maintaining clean Python code in general? Any challenges you've faced, or innovative solutions you've discovered?

Whether it's a question, a concern, or simply an interesting observation, I'm all ears. So don't hesitate—join the conversation. After all, the best way to learn is together. Let's enhance our coding journey by sharing and discussing our experiences.

Looking forward to hearing from you!