<jupyter_start><jupyter_text>Introduction To Python Exception Handling  What Is an Exception? From the [Python documentation](https://docs.python.org/3/tutorial/errors.html): *Even if a statement or expression is syntactically correct, it may cause an error when an attempt is made to execute it. Errors detected during execution are called exceptions and are not unconditionally fatal.* What will happen when you run the code below and why?<jupyter_code>n = 0
p = 10 * (1 / n)
print(p)<jupyter_output><empty_output><jupyter_text>Python's Built-in Construct for Handling Runtime Exceptions Is: `try...except` Examine and run the code below.  Why does `line 3` get executed if you enter the number 8, but it doesn't get executed if you enter the character 'A'?<jupyter_code>try:
    x = int(input("Enter an integer: "))
    print("Your integer is:", x)
except ValueError:
    print("Oops! Invalid integer.")

print("The program is finished")<jupyter_output><empty_output><jupyter_text>Python is extremely powerful.  Another way to handle errors from the code above is to capture the details from the `ValueError` exception as a variable and print them to the terminal.<jupyter_code>try:
    x = int(input("Enter an integer: "))
    print("Your integer is:", x)
except ValueError as e:
    print(e)

print("The program is finished")<jupyter_output><empty_output><jupyter_text>Some Python Exception Handling Best Practices  1. Make exceptions specificIn the example above, we're dealing with one specific exception `ValueError`.  Recall that Python's [input()](https://docs.python.org/3/library/functions.html) function always returns a string type and if we try to cast the string "42" to an int, it works fine.  If we try to cast the string "Navy" to an int, a `ValueError` exception is raised.  If we left the `ValueError` qualifier off our `except` clause, the code would still work, however we wouldn't able to determine exactly what caused the error or take specific actions based on specific errors.  To cover multiple exceptions, Python allows you to chain multiple `except` clauses within a single `try...except`.  Run the example below for a demonstration.<jupyter_code>L = ['N', 0, 3]

for item in L:
    try:
        print("Item is:", item)
        r = 1/int(item)
        print("Reciprocal is:", r)
    except ValueError:
        print("Cannot cast", item, "to int")
        # Additional code to handle ValueError
    except ZeroDivisionError:
        print("Item causes Division by Zero Error")
        # Additional code to handle ZeroDivisionError<jupyter_output><empty_output><jupyter_text>2. Use Only Where AppropriateException handling should only be used for situations that would cause run time errors.  Consider (and run) the example below. Not finding the desired sub-string is not a run time error, but trying to index beyond the end of the string is.<jupyter_code>s = "Go Navy, Beat Army!"
print(s.find("Beat"))   # "Beat" starts at index 9
print(s.find("Cyber"))  # "Cyber" is not contained in s, so find returns -1
size = len(s)
try:
    print(s[size])
    print("Success")
except IndexError as e:
    print(e)<jupyter_output><empty_output><jupyter_text>3. Exception Handling is Very Useful to Validate User InputThe example below demonstrates a common `try...except` use case for validating user input.<jupyter_code>while True:
    try:
        n = int(input("Enter an integer between 1 and 10: "))
        if (n < 1) or (n > 10):
            print("Input not between 1 and 10.  Please try again")
        else:
            break
    except ValueError:
        print("Invalid integer format.  Please try again.")

print("You entered:", n)<jupyter_output><empty_output>
StarcoderdataJupyterStructuredCleanDedup