Exceptions¶
This section deals with exceptions, which are language functions that specifically handle unusual circumstances during the execution of a programme. The most common exception is error handling, but they can also be used effectively for many other purposes. Python provides a comprehensive set of exceptions, and you can define new exceptions for your own purposes.
An exception is an object that is automatically created by Python functions with a raise statement, for example with:
11 if line == "":
12 raise EmptyFileError(f"{file} is empty")
The raise statement causes the Python programme to be
executed in a different way than is usually intended: The current call chain is
searched for a handler that can handle the generated exception. If such a
handler is found, it is called and can access the exception object to obtain
further information, as in our EmptyFileError
example:
1class EmptyFileError(Exception):
2 pass
This defines your own exception type, which inherits from the Exception
base
type.
You can find an overview of the class hierarchy of built-in exceptions at
Exception hierarchy in the
Python documentation. Each exception type is a Python class that inherits from
its parent exception type. For example, a ZeroDivisionError
is also an
ArithmeticError
, an Exception
and also a BaseException
by
inheritance. This hierarchy is intentional: most exceptions inherit from
Exception
, and it is strongly recommended that all user-defined exceptions
also subclass Exception
and not BaseException
:
It is possible to create different types of exceptions to reflect the actual cause of the reported error or exceptional circumstance.
8 try:
9 f = open(file, "r")
10 line = f.readline()
11 if line == "":
12 raise EmptyFileError(f"{file} is empty")
13 except OSError as error:
14 print(f"Cannot open file {file}: {error.strerror}")
15 except EmptyFileError as error:
16 print(error)
If an OSError
or an EmptyFileError
occurs in the try
block during
the execution of open()
, the corresponding except
block is executed.
If no suitable exception handler is found, the programme terminates with an
error message. We therefore add else
and finally
to our
try
-except
statements:
17 else:
18 print(f"{file}: {f.readline()}")
19 finally:
20 print("File", file, "processed")
21 f.close()
Now we can define a list of different file types so that our complete code looks like this:
1class EmptyFileError(Exception):
2 pass
3
4
5filenames = ["myFile1.py", "nonExistent.py", "emptyFile.py", "myFile2.py"]
6
7for file in filenames:
8 try:
9 f = open(file, "r")
10 line = f.readline()
11 if line == "":
12 raise EmptyFileError(f"{file} is empty")
13 except OSError as error:
14 print(f"Cannot open file {file}: {error.strerror}")
15 except EmptyFileError as error:
16 print(error)
17 else:
18 print(f"{file}: {f.readline()}")
19 finally:
20 print("File", file, "processed")
21 f.close()
- Line 7
If an
OSError
orEmptyFileError
occurs during the execution of the statements in thetry
block, the correspondingexcept
block is executed.- Line 9
An
OSError
could be triggered here.- Line 12
Here you trigger the
EmptyFileError
.- Line 17
The
else
clause is optional; it is executed if no exception occurs in thetry
block.- Line 19
The
finally
clause is also optional and is executed at the end of the block, regardless of whether an exception was triggered or not.
Note
The way Python handles error situations in general differs from some other languages, such as Java. These languages check possible errors as far as possible before they occur, as handling exceptions after they occur is costly. This is sometimes referred to as the LBYL approach.
Python, on the other hand, relies more on exceptions to handle errors after they occur. Although this reliance may seem risky, when exceptions are used correctly, the code is less cumbersome and easier to read, and errors are only handled when they occur. This Pythonic approach to error handling is often described as EAFP.
Checks¶
Write code that receives two numbers and divides the first number by the second. Check if the
ZeroDivisionError
occurs when the second number is0
and catch it.If
MyError
inherits fromException
, what is the difference betweenexcept Exception as e
andexcept MyError as e
?Write a simple program that receives a number and then uses the
assert()
statement to throw anexception
if the number is0
.Writes a user-defined exception
Outliers
that throws an exception if the variablex
is greater or less than3
?Is the check whether an object is a list (Check: list) programming in the style of LBYL or EAFP?