Introduction to try catch exception in Python
A program in python terminates as it encounters an error. Mainly there are two common errors; syntax error and exceptions.
Python exceptions are errors that happen during execution of the program. Python try
and except
statements are one of the important statements that can catch exceptions. I
n this tutorial we will cover Python exceptions in more details and will see how python try except
statements help us to try catch these exceptions along with examples. Moreover, we will also learn about some of the built-in exceptions in python and how to use them.
ALSO READ: Python struct module Explained [Easy Examples]
Difference between Python Exception and Error
Python exceptions and errors are two different things. There are some common differences between them which distinguish both from each other. These are the following differences between them.
- Errors cannot be handled, while Python exceptions can be catchd at the run time.
- The error indicates a problem that mainly occurs due to the lack of system resources while Exceptions are the problems which can occur at runtime and compile time. It mainly occurs in the code written by the developers.
- An error can be a syntax (parsing) error, while there can be many types of exceptions that could occur during the execution.
- An error might indicate critical problems that a reasonable application should not try to catch, while an exception might indicate conditions that an application should try to catch.
Different type of errors in Python
Errors are the problems in a program due to which the program will stop the execution. There can be different types of errors which might occur while coding. Some of which are Syntax error, recursion error and logical error. In this section we will closely look at each of these errors in more detail.
Syntax error in Python
When we run our python code, the first thing that interpreter will do is convert the code into python bytecode which then will be executed. If the interpreter finds any error/ invalid syntax during this state, it will not be able to convert our code into python code which means we have used invalid syntax somewhere in our code. The good thing is that most of the interpreters show us/give hints about the error which helps us to resolve it. If you are a beginner to Python language, you will see syntaxError
a lot while running your code.
ALSO READ: How to PROPERLY use break statement in Python [Easy Examples]
Here is an example showing the syntax error.
# defining variables
a = 10 b = 20
Output:
You can see the python is indicating the error and pointing to the error.
Recursion error in Python
This recursion error occurs when we call a function. As the name suggests, recursion error when too many methods, one inside another is executed with one an infinite recursion.
See the following simple example of recursion error:
# defining a function:
def main():
return main()
<i># calling the function</i>
main()
Output:
See the last line, which shows the error. We get a recursionError
because the function calls itself infinitely times without any break or other return statement.
Python exceptions
Sometimes, even if the syntax of the expression is correct, it may still cause an error when it executes. Such errors are called logical errors or exceptions. Logical errors are the errors that are detected during execution time and are not unconditionally fatal. Later in the tutorial we will cover how to catch these errors using python try except
method.
Again there can be many different kinds of Python exceptions you may face. Some of them are typeError
, ZeroDivisionError
, importError
and many more. We will see some of the examples of exceptions here.
See the example which gives typeError
when we try to add two different data types.
# string data type
name = "bashir"
<i># integer data type</i>
age = 21
# printing by adding int and string
print(age + name)
Output:
ALSO READ: 4 ways to add row to existing DataFrame in Pandas
Here is one more example which gives zeroDivisionError
when we try to divide some number by zero.
# zero division
print(23/0)
Output:
print(23/0)
ZeroDivisionError: division by zero
Now see the last example of import module error
. This error occurs when we import a module that does not exist.
# importing module
import abce
Output:
import abce
ModuleNotFoundError: No module named 'abce'
Python try catch exception
In Python, it is possible to write programs that catch selected exceptions. Python try except
statements are the most common way to catch Python exceptions. In this section we will cover some of the common ways using python try except
methods to catch different exceptions that might occur during the execution time of code.
Before going into the built-in python expedition handling statements, let us first learn how we can raise an exception if a condition is not fulfilled. In Python we use keyword raise to throw an exception. Let us say we want to take integer input from the user, and if the user enters a string value, then the program should throw an exception.
See the following example.
# taking input from user
number = "b"
# checkting type of variable
if type(number)==int:
pass
# execute else part if the variable if not int type
else:
raise TypeError("Only numeric values are required!!")
Output:
raise TypeError("Only numeric values are required!!")
TypeError: Only numeric values are required!!
ALSO READ: Python append() vs extend() in list [Practical Examples]
Python try except method to catch exception
As we already know that when syntactically correct code runs into an errors, then Python will throw an exception error. This exception will crash the program if not handled. The except
clause determines how our program responds to exceptions.
Python try
and except
statements are used to catch and handle such exceptions. Python will first execute the try
statement as a normal part of the program. If it successfully executes the try
block, then it will not go to the except
block. If the program catches any error during execution of the try
block, then the execution of the program will shift to the except
block.
Python try catch syntax
Python syntax to perform a try
and catch
can be achieved using following try except
block looks like this:
try:
## do normal statement
except Exception:
## handle the error
Example to catch exception with python try except
Let us now take a real example and try to divide some numeric value by zero. We know that if we do not handle the zeroError
our code will crash and will give us errors. See the example below how we managed to catch zeroError
using Python try
and except
block.
# Python try and except method
try:
print(23/0)
# Execute except block if zero division occurs
except ZeroDivisionError:
# handle zero division error
print("Cannot divide by zero!")
Output:
Cannot divide by zero!
Notice that our program executes successfully in spite of facing zeroDivisionError
.
In a similar way we can catch other exceptions that occur during execution of a program. Let us catch the import error that occurred during the import of unknown or uninstalled modules.
# Python try and except method
try:
import abcd
# execute except block if import error occurs
except ImportError:
# handle import error
print("Unable to import module!!")
Output:
Unable to import module!!
See the following example which catchs the TypeError
that occurs in Python when we try to add an integer with string.
# Python try and except method
try:
print(12 + "bashir")
# excute except block if type error occurs
except TypeError:
# handle type error
print("Strings cannot be added to integer")
Output:
Strings cannot be added to integer
ALSO READ: Python optional arguments in function [Practical Examples]
Python try except with ELSE to catch exception
The Python else
clause is useful when we want to run a piece of code only when there will be no error or exception. Because The code inside the else
block will be only executed if the try
clause does not raise an exception.
Python try and catch with else syntax
See the simple syntax of python try catch with else statement.
# try block
try:
# statements run if no exception occurs
except (name_of_exception):
# Handle exeption
# Else block only executes if no exception occurs
else:
# else statements
Python try and catch with else example
Now let us take a practical example to implement python try catch with else block. See the following example where the else
statement will only be executed if there will be no exception.
# Python try and except method
try:
number = 24/6
# execute except block if zero division occurs
except ZeroDivisionError:
# hanlde exception
print("Cannot divide by")
# Run this else block if no exception occurs
else:
print("the answer is {}".format(number))
Output:
the answer is 4.0
If we try to divide the number by 0 it will raise an exception and the else
statement will not be executed. See the example below:
# Python try and except method
try:
number = 24/0
#execute except blcok if zero division occurs
except ZeroDivisionError:
# handle exception
print("Cannot divide by zero")
# Executes else block only if no exception occurs
else:
print("the answer is {}".format(number))
Output:
Cannot divide by zero
Let us take one more example of the importing module as well using the python try except
and else
statement.
# Python try and except method
try:
import math
# Execute except block if module error accurs
except ModuleNotFoundError:
print("no module found!!")
# Execute else block only if no exception occurs
else:
print(math.pow(2, 3))
Output:
8.0
You can notice that the else
statement in python try except
only executes when the program does not produce any exceptions.
ALSO READ: Convert entire dataframe to lower case [SOLVED]
Python try expect with FINALLY to catch exception
We might come across a situation in our program when we want to execute the program even if an exception occurs. We can achieve this either by writing the piece of code in try
and except
both blocks ( which is not recommended when we have a large amount of code) or we can use the keyword finally. Finally, the statement is opposite of else
, it always executes after try
and except
blocks.
Python try and catch with finally syntax
Here is simple syntax of python try catch with finally block.
# try block
try:
# statements run if no exception occurs
except (name_of_exception):
# Hanlde exception
# this block will be executed always
# independent of except status
finally:
# final statements
Python try and catch with finally example
See the example below which uses finally block along with python try except
.
# Python try and except method
try:
number = 24/0
# execute except block if zero division occur
except ZeroDivisionError:
print("Cannot divide by zero")
# Always run finally block
finally:
print("This block successfully was executed!")
Output:
Cannot divide by zero
This block successfully was executed!
Notice that even our code produces ZeroDivisionError
but still the finally
block was executed successfully.
Now let us take one more example of importing a module without any exception.
# Python try and except method
try:
import math
# run except block if module error occurs
except ModuleNotFoundError:
print("No module exist")
# Always run finally block
finally:
print("Good job!")
Output:
Good job!
ALSO READ: 10+ simple examples to use Python string format in detail
Multiple EXCEPT clauses to catch exceptions in Python
So far in each example we have used only one except
block. However, Python allows us to use multiple except
blocks as well. While executing the try
block if there is an exception, then the very first exception block will be considered, if the first except
block catchs the exception, others will not be executed, else
each except
blocks will be checked respectively. Multiple except
clauses are helpful when we are not sure about the type of exception that might occur.
Syntax to catch multiple exceptions
Here is the simple syntax of multiple except
clauses.
# try and catch block
try:
# run try statements if no exception occurs
# run this block if exception_one occurs
except exception_one:
# handle exception_one
# run this block if exception_two occurs
except exception_two:
# hanlde exception_two
.
.
.
# run this block if exception_n occurs
exception exception_n:
# handle exception_n
Examples to catch multiple exceptions in Python
See the example below which uses multiple except
blocks in Python.
# Python try and except method
try:
import math
number = 24/6
print(number)
# run except block if module error occur
except ModuleNotFoundError:
print("No module exist")
# run except blcok if zero division occurs
except ZeroDivisionError:
print("Cannot divide by zero!")
# Always run finally block
finally:
print("Good job!")
Output:
4.0
Good job!
Now let us import an unknown module. See the example below:
# Python try and except method
try:
import abcd
number = 24/6
print(number)
#run except block if module error occurs
except ModuleNotFoundError:
print("No module exist")
# run this block if zero division occurs
except ZeroDivisionError:
print("Cannot divide by zero!")
# Always run finally block
finally:
print("Good job!")
Output:
No module exist
Good job!
ALSO READ: How to declare global variables in Python
The assertError exception handling in Python
Instead of waiting for a program to crash midway, we can also start making precautions by making assertions in Python. We can assert a condition that if this condition is met to be true then execute the program. And if the condition turns out to be False, we can have a program to throw an assertion error exception.
See the following example which shows how assertion works in Python
try:
denominator = 0
assert denominator != 0, "Cannot divide by zero"
print(24/ denominator)
# executes the assertionError if assert condition is false
except AssertionError as msg:
print(msg)
Output:
Cannot divide by zero
Summary
Python exceptions are inherited from the class BaseException
. Exceptions are throw by the interpreter while executing the programming and crashes when it come across any exception. In order to run our program successfully it is very important to catch such exceptions. In this tutorial we covered python exceptions, difference between and error and exceptions. Moreover, we learned about python try except
statements to catch expectations and also come across some of the important python built-in exceptions.
Further Reading
Python exceptions
try and except statement
More about python exceptions
The try except statement can handle exceptions. Exceptions may happen when you run a program.
Exceptions are errors that happen during execution of the program. Python won’t tell you about errors like syntax errors (grammar faults), instead it will abruptly stop.
An abrupt exit is bad for both the end user and developer.
Instead of an emergency halt, you can use a try except statement to properly deal with the problem. An emergency halt will happen if you do not properly handle exceptions.
Related course: Complete Python Programming Course & Exercises
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 FileNotFoundError
, ZeroDivisionError
or 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:
1 |
try: |
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.
1 |
try: |
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.pyDivided by zero
Should reach here
In the above example we catch the specific exception ZeroDivisionError. You can handle any exception like this:
1 |
try: |
You can write different logic for each type of exception that happens:
1 |
try: |
Related course: Complete Python Programming Course & Exercises
try-except
Lets take 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.
1 |
try: |
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:
1 |
finally: |
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:
1 |
def fail(): |
This outputs:
$ python3 example.pyException occured
Program continues
If you are a beginner, then I highly recommend this book.
try finally
A try-except block can have the finally clause (optionally). The finally clause is always executed.
So the general idea is:
1 |
try: |
For instance: if you open a file you’ll want to close it, you can do so in the finally clause.
1 |
try: |
try else
The else clause is executed if and only if no exception is raised. This is different from the finally clause that’s always executed.
1 |
try: |
Output:
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.
1 |
try: |
Raise Exception
Exceptions are raised when an error occurs. But in Python you can also force an exception to occur with the keyword raise
.
Any type of exception can be raised:
1 |
>>> raise MemoryError("Out of memory") |
1 |
>>> raise ValueError("Wrong value") |
Related course: Complete Python Programming Course & Exercises
Built-in exceptions
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 |
---|---|
AssertionError | if assert statement fails. |
AttributeError | if attribute assignment or reference fails. |
EOFError | if the input() functions hits end-of-file condition. |
FloatingPointError | if a floating point operation fails. |
GeneratorExit | Raise if a generator’s close() method is called. |
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. |
StopIteration | by next() function to indicate that there is no further item to be returned by iterator. |
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. |
SystemExit | by sys.exit() function. |
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. |
User-defined Exceptions
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.
1 |
class LunchError(Exception): |
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:
1 |
class NoMoneyException(Exception): |
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.
If you are a beginner, then I highly recommend this book.
Exercises
- Can try-except be used to catch invalid keyboard input?
- Can try-except catch the error if a file can’t be opened?
- When would you not use try-except?
Download examples
Error handling is an important aspect of coding. When errors are treated properly, the programs operate smoothly and cause no annoying crashes for the end users. In Python, error handling happens with a try-except code construct. (If you come from another programming language, there is no such thing as a try-catch statement in Python.)
The try-except code works such that it tries to run an expression or a piece of code. If the run fails, Python proceeds to run the actions in an except block. If the run succeeds, no further action is taken.
As a quick example, let’s try to print an undefined value and show an error if it fails:
try: print(x) except: print("Exception thrown. x does not exist.")
Output:
Exception thrown. x does not exist.
- Here the program tries to run the code inside the try block.
- If (and when) it fails, the except block catches the exception and logs it into the console.
This is a definitive guide to handling errors in Python. You will learn how to use the try…except structure for dealing with exceptions in your code. Besides, you learn how to handle multiple exceptions and how to add finally and else blocks in the error-handling code to always run actions. All the theory is backed up with great and illustrative examples.
Let’s jump into it!
What Is Error Handling in Coding?
Whenever you’re writing software code, there’s always a chance of something going wrong.
For example, if you expect a user to enter a number but they enter text instead, the program can crash if you haven’t prepared for such a faulty input.
Error handling is an important part of writing code that maintains the normal flow of your program without crashes and other annoyances.
If you’ve ever used a mobile app, and all of a sudden the app closes without warnings, there’s an unhandled error behind the scenes. It could be that the software code tries to read a value that doesn’t exist. Nonetheless, this is super annoying for the end users of your application, isn’t it?
When writing software code, you should always keep in mind what errors might occur to avoid the program causing annoying crashes.
As an example, if a Python function operates on the assumption that an input value is always an integer, it could lead to a crash if the input happens to be a string. To avoid crashes like this, you need to write the code such that it knows what to do if someone accidentally inputs a string instead of an integer.
This is where error handling helps. In Python, you can do error handling with a simple try-except code structure. The idea is to try to run a piece of code. If the trial fails, then the except block handles the error instead of letting the program crash.
In Python, you can use try-except statements to handle errors and exceptions that might happen when you run code.
Errors that take place during the execution of a program are called exceptions. In Python, faulty expressions raise errors and exceptions that will crash your program if you don’t handle the exceptions properly.
For example, a classic example of an exception is when you try to access an undefined value or divide a number by 0.
An abrupt crash is not beneficial for you as a developer needless to mention for the end users of your applications.
This is where the built-in error-handling mechanism helps. Instead of letting your program crash, you handle the errors during runtime and the program execution continues.
The error handling pattern in Python consists of the following:
- The try block. It runs a piece of code. If this piece of code fails, an exception is raised.
- The except block. This block catches the possible error raised by the try block. Also, you can (and should) specify the type of error you’re expecting from the try block here.
- The optional finally block runs a piece of code regardless of whether there were errors or not. This is an optional block of code you don’t need in the error handling scheme.
Here’s what a generic try except code structure looks like:
try: <actions> except Exception: <handle the exception here>
This code is pretty intuitive to read. The try specifies a block of code that Python tries to run. If the run fails, the except block catches an exception and runs some code.
Example
As an example, let’s run a try-except code to make sure the code doesn’t crash if a variable x is not defined:
try: print(x) except: print("Exception thrown. x does not exist.")
Notice that even though this piece of code prevents it from crashing, the way it’s written right now is bad practice. This is because we don’t define the type of error we expect in the except block.
Specify Error Type
To fix the earlier example, you need to know that when you’re accessing an undefined variable in Python, you should expect it to cause a NameError.
Now you can expect a potential NameError in the except block:
try: print(x) except NameError: print("NameError: x is not defined.")
Output:
NameError: x is not defined.
This not only makes the code more readable but also ensures you know what you’re doing. It’s much better to specify the type (or types) of error you might face instead of just catching a generic error.
Now, what if there is more than one exception that might occur? No problem. Python lets you define as many except blocks as needed.
Multiple Exceptions in Python Error Handling
In Python, you can have multiple except blocks for handling different types of errors separately.
try: <do something> except Exception1: <handle the this error type> except Exception2: <handle the this error type> except Exception3: <handle the this error type>
This is best demonstrated with an example.
Example
Let’s create a script that divides two numbers by one another. When it comes to dividing numbers, there are two things that could go wrong:
- One or both of the numbers are not defined.
- The denominator is zero.
The first problem will raise a NameError. The second issue causes a ZeroDivisionError.
To prevent crashes caused by these two potential issues, you need to handle both types of errors in your code. To do this, let’s specify some try-except error-handling logic in the code.
In the try-except structure, you want to handle both exceptions separately. Thus, you need two except blocks for the different cases:
try: result = x / y except ZeroDivisionError: print("Make sure no divisions by 0 are made.") except NameError: print("Make sure both numbers are defined.")
By the way, feel free to copy-paste the above code into your code editor and run the code to see what happens.
Now, because x and y are not defined, the program won’t crash thanks to the error handling you did. Instead, the program will print the message you specified that will be shown in case of a NameError:
Make sure both numbers are defined
Now, let’s define x and y, but let’s make y zero:
x = 10 y = 0 try: result = x / y except ZeroDivisionError: print("Make sure no divisions by 0 are made.") except NameError: print("Make sure both numbers are defined.")
Because dividing by 0 is mathematically not possible, this causes an error. But thanks to your careful error handling, this error doesn’t crash the program. Instead, it shows there was an error dividing by 0:
Make sure no divisions by 0 are made.
Finally, let’s write the code in a way that there are no longer errors:
x = 10 y = 5 try: result = x / y except ZeroDivisionError: print("Make sure no divisions by 0 are made.") except NameError: print("Make sure both numbers are defined.")
Now there is no error message. This means the program ran successfully because both x and y were defined and y was not 0.
Finally Block in Python Error Handling
In Python, you can add a finally block in the try-except error handling code. The finally block is an optional block that runs regardless of whether there were errors or not.
For instance, let’s run a function that does error handling without the finally block:
def run(): try: print(x) except: print("There was an error") return None print("Yay") run()
Output:
There was an error
Notice that the function never prints “Yay” because it returns before.
To print the “Yay” part of the code, you need to add a finally block in the error handling structure. The finally block will run no matter what. Even if the function returns a value, the finally block will run and finish what it has to in the error handling code.
def run(): try: print(x) except: print("There was an error") return None finally: print("Yay") run()
Output:
There was an error Yay
Else Block in Python Error Handling
You can also add an optional else block after except blocks in Python. The idea of an else block is to run code if there were no errors in the error handling sequence.
For example, let’s divide two numbers by one another, catch potential errors, and print a success message if no errors were thrown.
x = 15 y = 5 try: print(x / y) except ZeroDivisionError: print("Make sure no divisions by 0 are made.") else: print("There were no errors.")
Conclusion
In Python, there is no such thing as a try-catch statement. Instead, Python has its own version called try-except. The try-except code structure is used to deal with errors and exceptions.
Here is an example:
try: print(x) except: print("x is not defined") finally: print("Process finished")
Output:
x is not defined Process finished
Thanks for reading. Happy coding!
Further Reading
- 50 Python Interview Questions with Answers
- Finally Statement in Python
About the Author
- I’m an entrepreneur and a blogger from Finland. My goal is to make coding and tech easier for you with comprehensive guides and reviews.
Recent Posts
Содержание:развернуть
- Как устроен механизм исключений
- Как обрабатывать исключения в Python (try except)
-
As — сохраняет ошибку в переменную
-
Finally — выполняется всегда
-
Else — выполняется когда исключение не было вызвано
-
Несколько блоков except
-
Несколько типов исключений в одном блоке except
-
Raise — самостоятельный вызов исключений
-
Как пропустить ошибку
- Исключения в lambda функциях
- 20 типов встроенных исключений в Python
- Как создать свой тип Exception
Программа, написанная на языке Python, останавливается сразу как обнаружит ошибку. Ошибки могут быть (как минимум) двух типов:
- Синтаксические ошибки — возникают, когда написанное выражение не соответствует правилам языка (например, написана лишняя скобка);
- Исключения — возникают во время выполнения программы (например, при делении на ноль).
Синтаксические ошибки исправить просто (если вы используете IDE, он их подсветит). А вот с исключениями всё немного сложнее — не всегда при написании программы можно сказать возникнет или нет в данном месте исключение. Чтобы приложение продолжило работу при возникновении проблем, такие ошибки нужно перехватывать и обрабатывать с помощью блока try/except
.
Как устроен механизм исключений
В Python есть встроенные исключения, которые появляются после того как приложение находит ошибку. В этом случае текущий процесс временно приостанавливается и передает ошибку на уровень вверх до тех пор, пока она не будет обработано. Если ошибка не будет обработана, программа прекратит свою работу (а в консоли мы увидим Traceback с подробным описанием ошибки).
💁♂️ Пример: напишем скрипт, в котором функция ожидает число, а мы передаём сроку (это вызовет исключение «TypeError»):
def b(value):
print("-> b")
print(value + 1) # ошибка тут
def a(value):
print("-> a")
b(value)
a("10")
> -> a
> -> b
> Traceback (most recent call last):
> File "test.py", line 11, in <module>
> a("10")
> File "test.py", line 8, in a
> b(value)
> File "test.py", line 3, in b
> print(value + 1)
> TypeError: can only concatenate str (not "int") to str
В данном примере мы запускаем файл «test.py» (через консоль). Вызывается функция «a«, внутри которой вызывается функция «b«. Все работает хорошо до сточки print(value + 1)
. Тут интерпретатор понимает, что нельзя конкатенировать строку с числом, останавливает выполнение программы и вызывает исключение «TypeError».
Далее ошибка передается по цепочке в обратном направлении: «b» → «a» → «test.py«. Так как в данном примере мы не позаботились обработать эту ошибку, вся информация по ошибке отобразится в консоли в виде Traceback.
Traceback (трассировка) — это отчёт, содержащий вызовы функций, выполненные в определенный момент. Трассировка помогает узнать, что пошло не так и в каком месте это произошло.
Traceback лучше читать снизу вверх ↑
В нашем примере Traceback
содержится следующую информацию (читаем снизу вверх):
TypeError
— тип ошибки (означает, что операция не может быть выполнена с переменной этого типа);can only concatenate str (not "int") to str
— подробное описание ошибки (конкатенировать можно только строку со строкой);- Стек вызова функций (1-я линия — место, 2-я линия — код). В нашем примере видно, что в файле «test.py» на 11-й линии был вызов функции «a» со строковым аргументом «10». Далее был вызов функции «b».
print(value + 1)
это последнее, что было выполнено — тут и произошла ошибка. most recent call last
— означает, что самый последний вызов будет отображаться последним в стеке (в нашем примере последним выполнилсяprint(value + 1)
).
В Python ошибку можно перехватить, обработать, и продолжить выполнение программы — для этого используется конструкция try ... except ...
.
Как обрабатывать исключения в Python (try except)
В Python исключения обрабатываются с помощью блоков try/except
. Для этого операция, которая может вызвать исключение, помещается внутрь блока try
. А код, который должен быть выполнен при возникновении ошибки, находится внутри except
.
Например, вот как можно обработать ошибку деления на ноль:
try:
a = 7 / 0
except:
print('Ошибка! Деление на 0')
Здесь в блоке try
находится код a = 7 / 0
— при попытке его выполнить возникнет исключение и выполнится код в блоке except
(то есть будет выведено сообщение «Ошибка! Деление на 0»). После этого программа продолжит свое выполнение.
💭 PEP 8 рекомендует, по возможности, указывать конкретный тип исключения после ключевого слова except
(чтобы перехватывать и обрабатывать конкретные исключения):
try:
a = 7 / 0
except ZeroDivisionError:
print('Ошибка! Деление на 0')
Однако если вы хотите перехватывать все исключения, которые сигнализируют об ошибках программы, используйте тип исключения Exception
:
try:
a = 7 / 0
except Exception:
print('Любая ошибка!')
As — сохраняет ошибку в переменную
Перехваченная ошибка представляет собой объект класса, унаследованного от «BaseException». С помощью ключевого слова as
можно записать этот объект в переменную, чтобы обратиться к нему внутри блока except
:
try:
file = open('ok123.txt', 'r')
except FileNotFoundError as e:
print(e)
> [Errno 2] No such file or directory: 'ok123.txt'
В примере выше мы обращаемся к объекту класса «FileNotFoundError» (при выводе на экран через print
отобразится строка с полным описанием ошибки).
У каждого объекта есть поля, к которым можно обращаться (например если нужно логировать ошибку в собственном формате):
import datetime
now = datetime.datetime.now().strftime("%d-%m-%Y %H:%M:%S")
try:
file = open('ok123.txt', 'r')
except FileNotFoundError as e:
print(f"{now} [FileNotFoundError]: {e.strerror}, filename: {e.filename}")
> 20-11-2021 18:42:01 [FileNotFoundError]: No such file or directory, filename: ok123.txt
Finally — выполняется всегда
При обработке исключений можно после блока try
использовать блок finally
. Он похож на блок except
, но команды, написанные внутри него, выполняются обязательно. Если в блоке try
не возникнет исключения, то блок finally
выполнится так же, как и при наличии ошибки, и программа возобновит свою работу.
Обычно try/except
используется для перехвата исключений и восстановления нормальной работы приложения, а try/finally
для того, чтобы гарантировать выполнение определенных действий (например, для закрытия внешних ресурсов, таких как ранее открытые файлы).
В следующем примере откроем файл и обратимся к несуществующей строке:
file = open('ok.txt', 'r')
try:
lines = file.readlines()
print(lines[5])
finally:
file.close()
if file.closed:
print("файл закрыт!")
> файл закрыт!
> Traceback (most recent call last):
> File "test.py", line 5, in <module>
> print(lines[5])
> IndexError: list index out of range
Даже после исключения «IndexError», сработал код в секции finally
, который закрыл файл.
p.s. данный пример создан для демонстрации, в реальном проекте для работы с файлами лучше использовать менеджер контекста with.
Также можно использовать одновременно три блока try/except/finally
. В этом случае:
- в
try
— код, который может вызвать исключения; - в
except
— код, который должен выполниться при возникновении исключения; - в
finally
— код, который должен выполниться в любом случае.
def sum(a, b):
res = 0
try:
res = a + b
except TypeError:
res = int(a) + int(b)
finally:
print(f"a = {a}, b = {b}, res = {res}")
sum(1, "2")
> a = 1, b = 2, res = 3
Else — выполняется когда исключение не было вызвано
Иногда нужно выполнить определенные действия, когда код внутри блока try
не вызвал исключения. Для этого используется блок else
.
Допустим нужно вывести результат деления двух чисел и обработать исключения в случае попытки деления на ноль:
b = int(input('b = '))
c = int(input('c = '))
try:
a = b / c
except ZeroDivisionError:
print('Ошибка! Деление на 0')
else:
print(f"a = {a}")
> b = 10
> c = 1
> a = 10.0
В этом случае, если пользователь присвоит переменной «с» ноль, то появится исключение и будет выведено сообщение «‘Ошибка! Деление на 0′», а код внутри блока else
выполняться не будет. Если ошибки не будет, то на экране появятся результаты деления.
Несколько блоков except
В программе может возникнуть несколько исключений, например:
- Ошибка преобразования введенных значений к типу
float
(«ValueError»); - Деление на ноль («ZeroDivisionError»).
В Python, чтобы по-разному обрабатывать разные типы ошибок, создают несколько блоков except
:
try:
b = float(input('b = '))
c = float(input('c = '))
a = b / c
except ZeroDivisionError:
print('Ошибка! Деление на 0')
except ValueError:
print('Число введено неверно')
else:
print(f"a = {a}")
> b = 10
> c = 0
> Ошибка! Деление на 0
> b = 10
> c = питон
> Число введено неверно
Теперь для разных типов ошибок есть свой обработчик.
Несколько типов исключений в одном блоке except
Можно также обрабатывать в одном блоке except сразу несколько исключений. Для этого они записываются в круглых скобках, через запятую сразу после ключевого слова except
. Чтобы обработать сообщения «ZeroDivisionError» и «ValueError» в одном блоке записываем их следующим образом:
try:
b = float(input('b = '))
c = float(input('c = '))
a = b / c
except (ZeroDivisionError, ValueError) as er:
print(er)
else:
print('a = ', a)
При этом переменной er
присваивается объект того исключения, которое было вызвано. В результате на экран выводятся сведения о конкретной ошибке.
Raise — самостоятельный вызов исключений
Исключения можно генерировать самостоятельно — для этого нужно запустить оператор raise
.
min = 100
if min > 10:
raise Exception('min must be less than 10')
> Traceback (most recent call last):
> File "test.py", line 3, in <module>
> raise Exception('min value must be less than 10')
> Exception: min must be less than 10
Перехватываются такие сообщения точно так же, как и остальные:
min = 100
try:
if min > 10:
raise Exception('min must be less than 10')
except Exception:
print('Моя ошибка')
> Моя ошибка
Кроме того, ошибку можно обработать в блоке except
и пробросить дальше (вверх по стеку) с помощью raise
:
min = 100
try:
if min > 10:
raise Exception('min must be less than 10')
except Exception:
print('Моя ошибка')
raise
> Моя ошибка
> Traceback (most recent call last):
> File "test.py", line 5, in <module>
> raise Exception('min must be less than 10')
> Exception: min must be less than 10
Как пропустить ошибку
Иногда ошибку обрабатывать не нужно. В этом случае ее можно пропустить с помощью pass
:
try:
a = 7 / 0
except ZeroDivisionError:
pass
Исключения в lambda функциях
Обрабатывать исключения внутри lambda функций нельзя (так как lambda записывается в виде одного выражения). В этом случае нужно использовать именованную функцию.
20 типов встроенных исключений в Python
Иерархия классов для встроенных исключений в Python выглядит так:
BaseException
SystemExit
KeyboardInterrupt
GeneratorExit
Exception
ArithmeticError
AssertionError
...
...
...
ValueError
Warning
Все исключения в Python наследуются от базового BaseException
:
SystemExit
— системное исключение, вызываемое функциейsys.exit()
во время выхода из приложения;KeyboardInterrupt
— возникает при завершении программы пользователем (чаще всего при нажатии клавиш Ctrl+C);GeneratorExit
— вызывается методомclose
объектаgenerator
;Exception
— исключения, которые можно и нужно обрабатывать (предыдущие были системными и их трогать не рекомендуется).
От Exception
наследуются:
1 StopIteration
— вызывается функцией next в том случае если в итераторе закончились элементы;
2 ArithmeticError
— ошибки, возникающие при вычислении, бывают следующие типы:
FloatingPointError
— ошибки при выполнении вычислений с плавающей точкой (встречаются редко);OverflowError
— результат вычислений большой для текущего представления (не появляется при операциях с целыми числами, но может появиться в некоторых других случаях);ZeroDivisionError
— возникает при попытке деления на ноль.
3 AssertionError
— выражение, используемое в функции assert
неверно;
4 AttributeError
— у объекта отсутствует нужный атрибут;
5 BufferError
— операция, для выполнения которой требуется буфер, не выполнена;
6 EOFError
— ошибка чтения из файла;
7 ImportError
— ошибка импортирования модуля;
8 LookupError
— неверный индекс, делится на два типа:
IndexError
— индекс выходит за пределы диапазона элементов;KeyError
— индекс отсутствует (для словарей, множеств и подобных объектов);
9 MemoryError
— память переполнена;
10 NameError
— отсутствует переменная с данным именем;
11 OSError
— исключения, генерируемые операционной системой:
ChildProcessError
— ошибки, связанные с выполнением дочернего процесса;ConnectionError
— исключения связанные с подключениями (BrokenPipeError, ConnectionResetError, ConnectionRefusedError, ConnectionAbortedError);FileExistsError
— возникает при попытке создания уже существующего файла или директории;FileNotFoundError
— генерируется при попытке обращения к несуществующему файлу;InterruptedError
— возникает в том случае если системный вызов был прерван внешним сигналом;IsADirectoryError
— программа обращается к файлу, а это директория;NotADirectoryError
— приложение обращается к директории, а это файл;PermissionError
— прав доступа недостаточно для выполнения операции;ProcessLookupError
— процесс, к которому обращается приложение не запущен или отсутствует;TimeoutError
— время ожидания истекло;
12 ReferenceError
— попытка доступа к объекту с помощью слабой ссылки, когда объект не существует;
13 RuntimeError
— генерируется в случае, когда исключение не может быть классифицировано или не подпадает под любую другую категорию;
14 NotImplementedError
— абстрактные методы класса нуждаются в переопределении;
15 SyntaxError
— ошибка синтаксиса;
16 SystemError
— сигнализирует о внутренне ошибке;
17 TypeError
— операция не может быть выполнена с переменной этого типа;
18 ValueError
— возникает когда в функцию передается объект правильного типа, но имеющий некорректное значение;
19 UnicodeError
— исключение связанное с кодирование текста в unicode
, бывает трех видов:
UnicodeEncodeError
— ошибка кодирования;UnicodeDecodeError
— ошибка декодирования;UnicodeTranslateError
— ошибка переводаunicode
.
20 Warning
— предупреждение, некритическая ошибка.
💭 Посмотреть всю цепочку наследования конкретного типа исключения можно с помощью модуля inspect
:
import inspect
print(inspect.getmro(TimeoutError))
> (<class 'TimeoutError'>, <class 'OSError'>, <class 'Exception'>, <class 'BaseException'>, <class 'object'>)
📄 Подробное описание всех классов встроенных исключений в Python смотрите в официальной документации.
Как создать свой тип Exception
В Python можно создавать свои исключения. При этом есть одно обязательное условие: они должны быть потомками класса Exception
:
class MyError(Exception):
def __init__(self, text):
self.txt = text
try:
raise MyError('Моя ошибка')
except MyError as er:
print(er)
> Моя ошибка
С помощью try/except
контролируются и обрабатываются ошибки в приложении. Это особенно актуально для критически важных частей программы, где любые «падения» недопустимы (или могут привести к негативным последствиям). Например, если программа работает как «демон», падение приведет к полной остановке её работы. Или, например, при временном сбое соединения с базой данных, программа также прервёт своё выполнение (хотя можно было отловить ошибку и попробовать соединиться в БД заново).
Вместе с try/except
можно использовать дополнительные блоки. Если использовать все блоки описанные в статье, то код будет выглядеть так:
try:
# попробуем что-то сделать
except (ZeroDivisionError, ValueError) as e:
# обрабатываем исключения типа ZeroDivisionError или ValueError
except Exception as e:
# исключение не ZeroDivisionError и не ValueError
# поэтому обрабатываем исключение общего типа (унаследованное от Exception)
# сюда не сходят исключения типа GeneratorExit, KeyboardInterrupt, SystemExit
else:
# этот блок выполняется, если нет исключений
# если в этом блоке сделать return, он не будет вызван, пока не выполнился блок finally
finally:
# этот блок выполняется всегда, даже если нет исключений else будет проигнорирован
# если в этом блоке сделать return, то return в блоке
Подробнее о работе с исключениями в Python можно ознакомиться в официальной документации.
Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Raising and Handling Python Exceptions
A Python program terminates as soon as it encounters an error. In Python, an error can be a syntax error or an exception. In this article, you will see what an exception is and how it differs from a syntax error. After that, you will learn about raising exceptions and making assertions. Then, you’ll finish with a demonstration of the try and except block.
Exceptions versus Syntax Errors
Syntax errors occur when the parser detects an incorrect statement. Observe the following example:
>>> print( 0 / 0 ))
File "<stdin>", line 1
print( 0 / 0 ))
^
SyntaxError: invalid syntax
The arrow indicates where the parser ran into the syntax error. In this example, there was one bracket too many. Remove it and run your code again:
>>> print( 0 / 0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
This time, you ran into an exception error. This type of error occurs whenever syntactically correct Python code results in an error. The last line of the message indicated what type of exception error you ran into.
Instead of showing the message exception error
, Python details what type of exception error was encountered. In this case, it was a ZeroDivisionError
. Python comes with various built-in exceptions as well as the possibility to create self-defined exceptions.
Raising an Exception
We can use raise
to throw an exception if a condition occurs. The statement can be complemented with a custom exception.
If you want to throw an error when a certain condition occurs using raise
, you could go about it like this:
x = 10
if x > 5:
raise Exception('x should not exceed 5. The value of x was: {}'.format(x))
When you run this code, the output will be the following:
Traceback (most recent call last):
File "<input>", line 4, in <module>
Exception: x should not exceed 5. The value of x was: 10
The program comes to a halt and displays our exception to screen, offering clues about what went wrong.
The AssertionError
Exception
Instead of waiting for a program to crash midway, you can also start by making an assertion in Python. We assert
that a certain condition is met. If this condition turns out to be True
, then that is excellent! The program can continue. If the condition turns out to be False
, you can have the program throw an AssertionError
exception.
Have a look at the following example, where it is asserted that the code will be executed on a Linux system:
import sys
assert ('linux' in sys.platform), "This code runs on Linux only."
If you run this code on a Linux machine, the assertion passes. If you were to run this code on a Windows machine, the outcome of the assertion would be False
and the result would be the following:
Traceback (most recent call last):
File "<input>", line 2, in <module>
AssertionError: This code runs on Linux only.
In this example, throwing an AssertionError
exception is the last thing that the program will do. The program will come to halt and will not continue. What if that is not what you want?
The try
and except
Block: Handling Exceptions
The try
and except
block in Python is used to catch and handle exceptions. Python executes code following the try
statement as a “normal” part of the program. The code that follows the except
statement is the program’s response to any exceptions in the preceding try
clause.
As you saw earlier, when syntactically correct code runs into an error, Python will throw an exception error. This exception error will crash the program if it is unhandled. The except
clause determines how your program responds to exceptions.
The following function can help you understand the try
and except
block:
def linux_interaction():
assert ('linux' in sys.platform), "Function can only run on Linux systems."
print('Doing something.')
The linux_interaction()
can only run on a Linux system. The assert
in this function will throw an AssertionError
exception if you call it on an operating system other then Linux.
You can give the function a try
using the following code:
try:
linux_interaction()
except:
pass
The way you handled the error here is by handing out a pass
. If you were to run this code on a Windows machine, you would get the following output:
You got nothing. The good thing here is that the program did not crash. But it would be nice to see if some type of exception occurred whenever you ran your code. To this end, you can change the pass
into something that would generate an informative message, like so:
try:
linux_interaction()
except:
print('Linux function was not executed')
Execute this code on a Windows machine:
Linux function was not executed
When an exception occurs in a program running this function, the program will continue as well as inform you about the fact that the function call was not successful.
What you did not get to see was the type of error that was thrown as a result of the function call. In order to see exactly what went wrong, you would need to catch the error that the function threw.
The following code is an example where you capture the AssertionError
and output that message to screen:
try:
linux_interaction()
except AssertionError as error:
print(error)
print('The linux_interaction() function was not executed')
Running this function on a Windows machine outputs the following:
Function can only run on Linux systems.
The linux_interaction() function was not executed
The first message is the AssertionError
, informing you that the function can only be executed on a Linux machine. The second message tells you which function was not executed.
In the previous example, you called a function that you wrote yourself. When you executed the function, you caught the AssertionError
exception and printed it to screen.
Here’s another example where you open a file and use a built-in exception:
try:
with open('file.log') as file:
read_data = file.read()
except:
print('Could not open file.log')
If file.log does not exist, this block of code will output the following:
This is an informative message, and our program will still continue to run. In the Python docs, you can see that there are a lot of built-in exceptions that you can use here. One exception described on that page is the following:
Exception
FileNotFoundError
Raised when a file or directory is requested but doesn’t exist. Corresponds to errno ENOENT.
To catch this type of exception and print it to screen, you could use the following code:
try:
with open('file.log') as file:
read_data = file.read()
except FileNotFoundError as fnf_error:
print(fnf_error)
In this case, if file.log does not exist, the output will be the following:
[Errno 2] No such file or directory: 'file.log'
You can have more than one function call in your try
clause and anticipate catching various exceptions. A thing to note here is that the code in the try
clause will stop as soon as an exception is encountered.
Look at the following code. Here, you first call the linux_interaction()
function and then try to open a file:
try:
linux_interaction()
with open('file.log') as file:
read_data = file.read()
except FileNotFoundError as fnf_error:
print(fnf_error)
except AssertionError as error:
print(error)
print('Linux linux_interaction() function was not executed')
If the file does not exist, running this code on a Windows machine will output the following:
Function can only run on Linux systems.
Linux linux_interaction() function was not executed
Inside the try
clause, you ran into an exception immediately and did not get to the part where you attempt to open file.log. Now look at what happens when you run the code on a Linux machine:
[Errno 2] No such file or directory: 'file.log'
Here are the key takeaways:
- A
try
clause is executed up until the point where the first exception is encountered. - Inside the
except
clause, or the exception handler, you determine how the program responds to the exception. - You can anticipate multiple exceptions and differentiate how the program should respond to them.
- Avoid using bare
except
clauses.
The else
Clause
In Python, using the else
statement, you can instruct a program to execute a certain block of code only in the absence of exceptions.
Look at the following example:
try:
linux_interaction()
except AssertionError as error:
print(error)
else:
print('Executing the else clause.')
If you were to run this code on a Linux system, the output would be the following:
Doing something.
Executing the else clause.
Because the program did not run into any exceptions, the else
clause was executed.
You can also try
to run code inside the else
clause and catch possible exceptions there as well:
try:
linux_interaction()
except AssertionError as error:
print(error)
else:
try:
with open('file.log') as file:
read_data = file.read()
except FileNotFoundError as fnf_error:
print(fnf_error)
If you were to execute this code on a Linux machine, you would get the following result:
Doing something.
[Errno 2] No such file or directory: 'file.log'
From the output, you can see that the linux_interaction()
function ran. Because no exceptions were encountered, an attempt to open file.log was made. That file did not exist, and instead of opening the file, you caught the FileNotFoundError
exception.
Cleaning Up After Using finally
Imagine that you always had to implement some sort of action to clean up after executing your code. Python enables you to do so using the finally
clause.
Have a look at the following example:
try:
linux_interaction()
except AssertionError as error:
print(error)
else:
try:
with open('file.log') as file:
read_data = file.read()
except FileNotFoundError as fnf_error:
print(fnf_error)
finally:
print('Cleaning up, irrespective of any exceptions.')
In the previous code, everything in the finally
clause will be executed. It does not matter if you encounter an exception somewhere in the try
or else
clauses. Running the previous code on a Windows machine would output the following:
Function can only run on Linux systems.
Cleaning up, irrespective of any exceptions.
Summing Up
After seeing the difference between syntax errors and exceptions, you learned about various ways to raise, catch, and handle exceptions in Python. In this article, you saw the following options:
raise
allows you to throw an exception at any time.assert
enables you to verify if a certain condition is met and throw an exception if it isn’t.- In the
try
clause, all statements are executed until an exception is encountered. except
is used to catch and handle the exception(s) that are encountered in the try clause.else
lets you code sections that should run only when no exceptions are encountered in the try clause.finally
enables you to execute sections of code that should always run, with or without any previously encountered exceptions.
Hopefully, this article helped you understand the basic tools that Python has to offer when dealing with exceptions.
Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Raising and Handling Python Exceptions
Python exception handling is the process of identifying and responding to errors in a program. In other words, it is a way to deal with errors that might occur in your program. In this article, you will learn how to handle errors in Python by using the Python try
and except
keywords. It will also teach you how to create custom exceptions, which can be used to define your own specific error messages.
Table of Contents
- 1 What is an exception?
- 2 Python try except
- 3 Catching exceptions with try except
- 4 The finally and else blocks
- 5 Common Python exceptions
- 6 Exception best practices
- 7 Create custom exceptions
- 8 Raising (or throwing) exceptions
- 9 How to print a Python exception
- 10 Keep learning
What is an exception?
An exception is a condition that arises during the execution of a program. It is a signal that something unexpected happened. Python represents exceptions by an object of a certain type.
In Python, all built-in, non-system-exiting exceptions are derived from the Exception
class. Exceptions have their own, descriptive names. For example, if you try to divide a number by zero, you will get a ZeroDivisionError
exception, which is also a subclass of the Exception
class.
For a complete hierarchy of all exceptions, you can view the Python manual if you’re interested. Here’s a small excerpt from this hierarchy, just to illustrate:
BaseException +-- SystemExit +-- KeyboardInterrupt +-- Exception +-- ArithmeticError | +-- FloatingPointError | +-- OverflowError | +-- ZeroDivisionError .....
In case your knowledge about objects, classes, and inheritance is a bit rusty, you may want to read my article on objects and classes and my article on inheritance first.
When something unexpected occurs, we can raise an exception at the point of the error. When an exception is raised, Python stops the current flow of execution and starts looking for an exception handler that can handle it. So what is an exception handler? Here’s where the try and except statements come into play.
As demonstrated in the illustration, we can create a block of code by starting with a try statement. This basically means: try to run this code, but an exception might occur.
After our try block, one or more except blocks must follow. This is where the magic happens. These except blocks can catch an exception, as we usually call this. In fact, many other programming languages use a statement called catch
instead of except
. Each except
block can handle a specific type of exception.
Remember: classes are hierarchical. For that reason, exceptions are too. Hence, except blocks must go from most specific, like a ZeroDivisionError
, to less specific, like an ArithmeticError
.
To demonstrate this, imagine what happens when we would start with an except block that catches Exception
. This first block would catch basically everything, because most exceptions inherit from this one, rendering the other except blocks useless.
Now let’s first go back to raising an exception. When an exception is raised, the exception handler that’s able to handle the exception can be nearby, but it can also be in a different module. What’s important to realize, is that Python won’t just scan your code at random for an exception handler. Instead, the handler should be somewhere in the call stack.
Please forget about else
and finally
for now. I’ll explain them in detail further down in this article. We first need to discuss call stacks, to truly understand how an exception finds its way to an exception handler.
Call stack
A call stack is an ordered list of functions that are currently being executed. For example, you might call function A, which calls function B, which calls function C. We now have a call stack consisting of A, B, and C. When C raises an exception, Python will look for an exception handler in this call stack, going backward from end to start. It can be in function C (closest to the exception), in function B (somewhat farther), in function A, or even at the top level of the program where we called function A.
If Python finds a suitable except block, it executes the code in that block. If it doesn’t find one, Python handles the exception by itself. This means it will print the exception and exit the program since it has no clue what to do with it.
I hope you’re still with me! If not, no worries. The examples on this page will hopefully make all this more clear. You might want to revisit this section once you’ve finished the entire article.
Catching exceptions with try except
Let’s finally write some actual code! To handle an exception, we need to catch it. As we just learned, we can catch an exception by using the try
and except
keywords. When an exception occurs while we are inside the try
block, the code in the except
block is executed.
A simple example
Let’s try a simple example first. As you hopefully know, we can’t divide by the number zero. If we do so anyway, Python will throw and exception called ZeroDivisionError
, which is a subclass of ArithmeticError
:
try: print(2/0) except ZeroDivisionError: print("You can't divide by zero!")
If you call a Python function inside the try block, and an exception occurs in that function, the flow of code execution stops at the point of the exception and the code in the except block is executed. Try doing this again, without try and except. You’ll see that Python prints the exception for us. You can do so in the following code crumb:
Also, note that Python prints the error to stderr if you don’t handle the exception by yourself. In the crumb above, this is visible because the output appears in an ‘Error’ tab instead of an ‘Output’ tab.
Catching IOError
Let’s try another, more common example. After all, who divides a number by zero, right?
Exceptions are likely to occur when interacting with the outside world, e.g. when working with files or networks. For example, if you try to open a file with Python, but that file doesn’t exist, you will get an IOError
exception. If you don’t have access to a file due to permissions, you will again get an IOError
exception. Let’s see how to handle these exceptions.
Assignment
Please do the following:
- Run the code below, notice the file name (it doesn’t exist). See what happens.
- Alter the file name to myfile.txt file and run the code again. What happens now?
Alternatively, here’s the code to copy/paste:
try: # Open file in read-only mode with open("not_here.txt", 'r') as f: f.write("Hello World!") except IOError as e: print("An error occurred:", e)
Answers
The file is not found in the first case. You should get this output:
An error occurred: [Errno 2] No such file or directory: 'not_here.txt'
In the second case, you’ll still get an error after creating the file. This time because we’re trying to write to a file that is opened in read-only mode. For more information on these modes, read the article on opening, reading, and writing files with Python. The error should look like this:
An error occurred: not writable
Although this is an error, it’s not written to the stderr output of the operating system. That’s because we handled the exception ourselves. If you removed the try.. except from the code completely and then try to write to the file in read-only mode, Python will catch the error, force the program to terminate, and show this message:
Traceback (most recent call last): File "tryexcept.py", line 3, in <module> f.write("Hello World!") io.UnsupportedOperation: not writable
The finally and else blocks
Remember the other two blocks that I asked you to forget for a while? Let’s look at those now, starting with the finally
block.
The finally block in try-except
The finally
block is executed regardless of whether an exception occurs or not. Finally
blocks are useful, for example, when you want to close a file or a network connection regardless of what happens. After all, you want to clean up resources to prevent memory leaks.
Here’s an example of this at work, in which we open a file without using the with statement
, forcing us to close it ourselves:
try: # Open file in write-mode f = open("myfile.txt", 'w') f.write("Hello World!") except IOError as e: print("An error occurred:", e) finally: print("Closing the file now") f.close()
You can also try this interactive example:
You should see the ‘Closing the file now’ message printed on your screen. Now change the writing mode to ‘r’ instead of ‘w’. You’ll get an error since the file does not exist. Despite this exception, we try to close the file anyway thanks to the finally block. This in turn goes wrong too: a NameError
exception is thrown because the file was never opened, and hence f
does not exist. You can fix this with a nested try.. except NameError
. Try it for yourself.
The else block in try-except
In addition to the except
and finally
blocks, you can add an else block. The else block executes only when no exception occurs. So it differs from the finally block, since finally executes even if an exception occurs.
When should you use the else
block? And why shouldn’t you just add extra code to the try
block? Good questions!
According to the Python manual, the use of the else clause is better than adding additional code to the try clause. But why? The reasoning is that it avoids accidentally catching an exception that wasn’t raised by the code being protected by the try and except statements in the first place. I admit I don’t use else blocks very often myself. Also, I find them somewhat confusing, especially for people coming from other languages.
Common Python exceptions
Some exceptions are so common that you’ll inevitably encounter them. Here are a few of the most common ones:
Exception name | When you’ll encounter it | Example situation that raises the exception |
SyntaxError | Raised when there is an error in Python syntax. If not caught, this exception will cause the Python interpreter to exit. | pritn('test') |
KeyError | Raised when a key is not found in a dictionary. | d = { 'a': 1} |
IndexError | Raised when an index is out of range. | lst = [1, 2, 3] |
KeyboardInterrupt | Raised when the user hits the interrupt key (Ctrl+C) | Pressing control+c |
If you like, you can try to evoke these exceptions intentionally. I’ll promise you, you will encounter these countless times in your Python programming career. Knowing and understanding what they mean and when they occur will greatly help you debug your code.
Exception best practices
Now that we know the mechanics of handling exceptions, there are a couple of best practices I’d like to share with you.
Don’t use blank except blocks
I’ve written about this before in the blog post ‘How not to handle exceptions in Python‘. Don’t use a blank block when you want to catch a broad range of exceptions. By this, I mean something like:
try: ... except: print("An error occurred:")
You might encounter this in code samples on the web. If you do, make a habit of improving the exception handling. Why should you, and how can you improve code like the example above?
All exceptions, including system exceptions, inherit from a class called BaseException
. If an except
clause mentions a particular class, that clause also handles any exception classes derived from that class. An empty except
is equivalent to except BaseException
, hence it will catch all possible exceptions.
So although the syntax is allowed, I don’t recommend it. E.g., you’ll also catch KeyboardInterrupt
and SystemExit
exceptions, which prevent your program from exiting. Instead, use a try block with a list of explicit exceptions that you know you can handle. Or, if you really need to, catch the Exception
base class to handle almost all the regular exceptions, but not the system ones.
If you’re feeling adventurous, you can try to catch all exceptions and see what happens:
from time import sleep while True: try: print("Try and stop me") sleep(1) except: print("Don't stop me now, I'm having such a good time!")
You’ll probably need to close your terminal to stop this program. Now change the except block to catch Exception
. You will still catch almost all exceptions, but the program will exit on system exceptions like KeyboardInterrupt
and SystemExit
:
from time import sleep while True: try: print("Try and stop me") sleep(1) except Exception: print("Something went wrong")
It’s better to ask for forgiveness
In Python, you’ll often see a pattern where people simply try if something works, and if it doesn’t, catch the exception. In other words, it’s better to ask for forgiveness than permission. This is in contrast to other languages, where you preferably ask for permission. E.g., in Java, exceptions can slow down your program and you “ask for permission” by doing checks on an object instead of simply trying.
To make this more concrete: in Python, we often just try to access the key in a dictionary. If the key doesn’t exist, we’ll get an exception and handle it. Suppose we just converted some externally provided JSON to a dictionary, and now start to use it:
import json user_json = '{"name": "John", "age": 39}' user = json.loads(user_json) try: print(user['name']) print(user['age']) print(user['address']) ... except KeyError as e: print("There are missing fields in the user object: ", e) # Properly handle the error ...
This will print the error:
There are missing fields in the user object: 'address'
We could have added three checks (if 'name' in user
, if 'age' in user
, etc.) to make sure that all the fields are there. But this is not a good practice. It potentially introduces a lot of code just to check if keys exist. Instead, we ask for forgiveness in our except block once, which is much cleaner and more readable. And if you worry about performance: exceptions don’t take up that many CPU cycles in Python. Lots of comparisons are in fact slower than catching a single exception (if it occurs at all!).
Create custom exceptions
All built-in, non-system-exiting exceptions are derived from the Exception
class as we learned before. All user-defined exceptions should also be derived from this class. So if we want to create our own exceptions, we need to create a subclass of the Exception
class.
For example, if you want to create an exception that indicates that a user was not found, you can create a UserNotFoundError
exception. This would, in its most basic form, look like this:
class UserNotFoundError(Exception): pass
This inherits all the properties and methods of Exception
, but we give it a new name to distinguish it from the Exception
class. This way, we’ll be able to specifically catch it with an except block.
The name of this exception clearly tells us the type of problem that was encountered, so as an added bonus, it functions as a form of code documentation as well. Just like well-named variables and functions, a well-named exception can be a big difference when reading back your code.
We’ll use this class in the example that follows.
Raising (or throwing) exceptions
We know some built-in exceptions and how to create custom exceptions. We also know how to catch exceptions with try and except. What’s left, is what’s called raising or throwing an exception. You can raise an exception yourself with the raise keyword.
In the example below, we use your previously defined UserNotFoundError
. We call a function, fetch_user
, that fetches some user data from an imaginary database. If the user is not found, this database returns None. We decided that we don’t want to return None, which would force the caller to check for None every time. Instead, we use our custom UserNotFoundError
.
class UserNotFoundError(Exception): pass def fetch_user(user_id): # Here you would fetch from some kind of db, e.g.: # user = db.get_user(user_id) # To make this example runnable, let's set it to None user = None if user == None: raise UserNotFoundError(f'User {user_id} not in database') else: return user users = [123, 456, 789] for user_id in users: try: fetch_user(user_id) except UserNotFoundError as e: print("There was an error: ", e)
Assignment
Here’s a little assignment. We could have used a regular Exception object instead. That way, we don’t need to define a custom one. Why is this a bad idea?
Answer
You can in fact raise a regular exception, e.g. with raise Exception('User not found')
. But if you do, you need to catch all exceptions of type Exception. And as we know, there are a lot of those. Chances are you inadvertently catch some other exception that you’re not able to handle. For example, the database client might throw a DatabaseAuthenticationError
which is also a subclass of Exception
.
How to print a Python exception
You can print exceptions directly as long as you catch them properly. You may have seen examples of this above already. To be clear, here’s an example of how to catch and print an exception:
try: ... except Exception as e: print("There was an error: ", e)
If you’d like to print the call stack, just like Python does when you don’t catch the exception yourself, you can import the traceback module:
import traceback try: ... except Exception: traceback.print_exc()
Keep learning
Here are some more resources to deepen your knowledge:
- My blog article ‘How not to handle exceptions in Python‘
- Introduction to Python functions
- Objects and classes, and Python inheritance
- The official documentation on exceptions.
- The official documentation on errors.
Are you enjoying this free tutorial? Please also have a look at my premium courses. They offer a superior user experience with small, easy-to-digest lessons and topics, progress tracking, quizzes to test your knowledge, and practice sessions. Each course will earn you a downloadable course certificate.
Error in Python can be of two types i.e. Syntax errors and Exceptions. Errors are the problems in a program due to which the program will stop the execution. On the other hand, exceptions are raised when some internal events occur which changes the normal flow of the program.
Note: For more information, refer to Errors and Exceptions in Python
Some of the common Exception Errors are :
- IOError: if the file can’t be opened
- KeyboardInterrupt: when an unrequired key is pressed by the user
- ValueError: when built-in function receives a wrong argument
- EOFError: if End-Of-File is hit without reading any data
- ImportError: if it is unable to find the module
Try Except in Python
Try and Except statement is used to handle these errors within our code in Python. The try block is used to check some code for errors i.e the code inside the try block will execute when there is no error in the program. Whereas the code inside the except block will execute whenever the program encounters some error in the preceding try block.
Syntax:
try: # Some Code except: # Executed if error in the # try block
How try() works?
- First, the try clause is executed i.e. the code between try and except clause.
- If there is no exception, then only the try clause will run, except the clause is finished.
- If any exception occurs, the try clause will be skipped and except clause will run.
- If any exception occurs, but the except clause within the code doesn’t handle it, it is passed on to the outer try statements. If the exception is left unhandled, then the execution stops.
- A try statement can have more than one except clause
Code 1: No exception, so the try clause will run.
Python3
def
divide(x, y):
try
:
result
=
x
/
/
y
print
(
"Yeah ! Your answer is :"
, result)
except
ZeroDivisionError:
print
(
"Sorry ! You are dividing by zero "
)
divide(
3
,
2
)
Auxiliary Space: O(1)
Output :
('Yeah ! Your answer is :', 1)
Code 1: There is an exception so only except clause will run.
Python3
def
divide(x, y):
try
:
result
=
x
/
/
y
print
(
"Yeah ! Your answer is :"
, result)
except
ZeroDivisionError:
print
(
"Sorry ! You are dividing by zero "
)
divide(
3
,
0
)
Output :
Sorry ! You are dividing by zero
Else Clause
In python, you can also use the else clause on the try-except block which must be present after all the except clauses. The code enters the else block only if the try clause does not raise an exception.
Syntax:
try: # Some Code except: # Executed if error in the # try block else: # execute if no exception
Code:
Python3
def
AbyB(a , b):
try
:
c
=
((a
+
b)
/
/
(a
-
b))
except
ZeroDivisionError:
print
(
"a/b result in 0"
)
else
:
print
(c)
AbyB(
2.0
,
3.0
)
AbyB(
3.0
,
3.0
)
Output:
-5.0 a/b result in 0
Finally Keyword in Python
Python provides a keyword finally, which is always executed after the try and except blocks. The final block always executes after normal termination of try block or after try block terminates due to some exceptions.
Syntax:
try: # Some Code except: # Executed if error in the # try block else: # execute if no exception finally: # Some code .....(always executed)
Code:
Python3
try
:
k
=
5
/
/
0
print
(k)
except
ZeroDivisionError:
print
(
"Can't divide by zero"
)
finally
:
print
(
'This is always executed'
)
Output:
Can't divide by zero This is always executed
Related Articles:
- Output Questions
- Exception Handling in Python
- User-Defined Exceptions
This article is contributed by Mohit Gupta_OMG 😀. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.