Table of Contents
What are exceptions in Python?
Python has built-in exceptions which can output an error. If an error occurs while running the program, it’s called an exception.
If an exception occurs, the type of exception is shown. Exceptions needs to be dealt with or the program will crash. To handle exceptions, the
try-catch block is used.
Some exceptions you may have seen before are
ImportError but there are many more.
All exceptions in Python inherit from the class BaseException. If you open the Python interactive shell and type the following statement it will list all built-in exceptions:
The idea of the try-except clause is to handle exceptions (errors at runtime). The syntax of the try-except block is:
try: <do something> except Exception: <handle the error>
The idea of the try-except block is this:
- try: the code with the exception(s) to catch. If an exception is raised, it jumps straight into the except block.
- except: this code is only executed if an exception occured in the try block. The except block is required with a try block, even if it contains only the pass statement.
It may be combined with the else and finally keywords.
- else: Code in the else block is only executed if no exceptions were raised in the try block.
- finally: The code in the finally block is always executed, regardless of if a an exception was raised or not.
Catching Exceptions in Python
The try-except block can handle exceptions. This prevents abrupt exits of the program on error. In the example below we purposely raise an exception.
try: 1 / 0 except ZeroDivisionError: print('Divided by zero') print('Should reach here')
After the except block, the program continues. Without a try-except block, the last line wouldn’t be reached as the program would crash.
$ python3 example.py Divided by zero Should reach here
In the above example we catch the specific exception ZeroDivisionError. You can handle any exception like this:
try: open("fantasy.txt") except: print('Something went wrong') print('Should reach here')
You can write different logic for each type of exception that happens:
try: # your code here except FileNotFoundError: # handle exception except IsADirectoryError: # handle exception except: # all other types of exceptions print('Should reach here')
Let us do a real world example of the try-except block.
The program asks for numeric user input. Instead the user types characters in the input box. The program normally would crash. But with a try-except block it can be handled properly.
The try except statement prevents the program from crashing and properly deals with it.
try: x = input("Enter number: ") x = x + 1 print(x) except: print("Invalid input")
Entering invalid input, makes the program continue normally:
The try except statement can be extended with the finally keyword, this will be executed if no exception is thrown:
finally: print("Valid input.")
The program continues execution if no exception has been thrown.
There are different kinds of exceptions: ZeroDivisionError, NameError, TypeError and so on. Sometimes modules define their own exceptions.
The try-except block works for function calls too:
def fail(): 1 / 0 try: fail() except: print('Exception occured') print('Program continues')
$ python3 example.py Exception occured Program continues
A try-except block can have the finally clause (optionally). The finally clause is always executed.
So the general idea is:
try: <do something> except Exception: <handle the error> finally: <cleanup>
For instance: if you open a file you’ll want to close it, you can do so in the finally clause.
try: f = open("test.txt") except: print('Could not open file') finally: f.close() print('Program continue')
The else clause is executed if and only if no exception is raised. This is different from the finally clause that’s always executed.
try: x = 1 except: print('Failed to set x') else: print('No exception occured') finally: print('We always do this')
No exception occured We always do this
You can catch many types of exceptions this way, where the else clause is executed only if no exception happens.
try: lunch() except SyntaxError: print('Fix your syntax') except TypeError: print('Oh no! A TypeError has occured') except ValueError: print('A ValueError occured!') except ZeroDivisionError: print('Did by zero?') else: print('No exception') finally: print('Ok then')
Exceptions are raised when an error occurs. But in Python you can also force an exception to occur with the keyword
Any type of exception can be raised:
raise MemoryError("Out of memory") Traceback (most recent call last): File "<stdin>", line 1, in <module> MemoryError: Out of memory
raise ValueError("Wrong value") Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: Wrong value >>>
A list of Python’s Built-in Exceptions is shown below. This list shows the Exception and why it is thrown (raised).
|Exception||Cause of Error|
|AttributeError||if attribute assignment or reference fails.|
|FloatingPointError||if a floating point operation fails.|
|GeneratorExit||Raise if a generator’s
|ImportError||if the imported module is not found.|
|IndexError||if index of a sequence is out of range.|
|KeyError||if a key is not found in a dictionary.|
|KeyboardInterrupt||if the user hits interrupt key (Ctrl+c or delete).|
|MemoryError||if an operation runs out of memory.|
|NameError||if a variable is not found in local or global scope.|
|NotImplementedError||by abstract methods.|
|OSError||if system operation causes system related error.|
|OverflowError||if result of an arithmetic operation is too large to be represented.|
|ReferenceError||if a weak reference proxy is used to access a garbage collected referent.|
|RuntimeError||if an error does not fall under any other category.|
|SyntaxError||by parser if syntax error is encountered.|
|IndentationError||if there is incorrect indentation.|
|TabError||if indentation consists of inconsistent tabs and spaces.|
|SystemError||if interpreter detects internal error.|
|TypeError||if a function or operation is applied to an object of incorrect type.|
|UnboundLocalError||if a reference is made to a local variable in a function or method, but no value has been bound to that variable.|
|UnicodeError||if a Unicode-related encoding or decoding error occurs.|
|UnicodeEncodeError||if a Unicode-related error occurs during encoding.|
|UnicodeDecodeError||if a Unicode-related error occurs during decoding.|
|UnicodeTranslateError||if a Unicode-related error occurs during translating.|
|ValueError||if a function gets argument of correct type but improper value.|
|ZeroDivisionError||if second operand of division or modulo operation is zero.|
Python has many standard types of exceptions, but they may not always serve your purpose.
Your program can have your own type of exceptions.
To create a user-defined exception, you have to create a class that inherits from Exception.
class LunchError(Exception): pass raise LunchError("Programmer went to lunch")
You made a user-defined exception named LunchError in the above code. You can raise this new exception if an error occurs.
Outputs your custom error:
$ python3 example.py Traceback (most recent call last): File “example.py”, line 5, in raise LunchError(“Programmer went to lunch”) main.LunchError: Programmer went to lunch
Your program can have many user-defined exceptions. The program below throws exceptions based on a new projects money:
class NoMoneyException(Exception): pass class OutOfBudget(Exception): pass balance = int(input("Enter a balance: ")) if balance < 1000: raise NoMoneyException elif balance > 10000: raise OutOfBudget
Here are some sample runs:
$ python3 example.py Enter a balance: 500 Traceback (most recent call last): File “example.py”, line 10, in raise NoMoneyException main.NoMoneyException
$ python3 example.py $ python3 example.py Enter a balance: 100000 Traceback (most recent call last): File “example.py”, line 12, in raise OutOfBudget main.OutOfBudget
It is a good practice to put all user-defined exceptions in a separate file (exceptions.py or errors.py). This is common practice in standard modules too.