Exceptions give us the ability to handle errors when they occur. We use try/catch in order to deal with errors when they occur.

try:
    # Your code
except <ERRORNO1>:
    # handle <ERRORNO1>
except <ERRORNO2>:
    # handle <ERRORNO2>

In the above code we have exception handling depending on the error that gets thrown during the execution of the program. If we wanted to catch all exceptions, we simply have the except without any errors after it like so:

try:
    # Your code
except:
    # catch any exception regardless of error type

If we use conditionals in our code (if/else), we put the else after the exception and the code will continue executing as long as no exception has been thrown:

try:
    # Your code
except:
    # catch any exception regardless of error type
else:
    # Rest of the code is executed as long as there were no exceptions thrown

We can also add finally to our code. The code under finally will execute regardless of whether an exception is thrown or not.

try:
    # Your code
except:
    # catch any exception regardless of error type
else:
    # Rest of the code is executed as long as there were no exceptions thrown
finally:
    # Execute code here regardless of whether an exception was thrown or not

You can throw an exception by using the keyword raise:

raise Exception('Error! Something went wrong')

We can catch the above exception that was raised by doing the following:

try:
    # Some code
    raise Exception('Error! Something went wrong')
except Exception as error: # Catch exception
    # Code to handle exception

Python also allows us to create our own exceptions by creating a class like so:

class ItemNotFoundException(Exception):
    pass # pass is a keyword that we use in order for Python not throw an error when there is no code 
try:
    raise ItemNotFoundException()
except ItemNotFoundException:
    # Code to handle exception