Exceptions#
Exceptions is a cases in program when it is syntactically correct but there some other cases doesn’t expected to be normal.
Check more on the:
Errors and Exceptions page of the official documentation.
Build it exceptions list with descriptions of the built-in python exceptions.
try/except
#
This section considers the syntax of the try/except
block. The following code demonstrates various syntax tricks available in the try/except
statement.
try:
# try block
...
except <Exception type> as <object>:
# exception block 1
except <Exception type>:
# exception block 2
except (<Exception type 1>, <Exception type 2>) as v:
# exception block 3
except (<Exception type 1>, <Exception type 2>)
# exception block 4
except:
# exception block 5
else: # optional
# else block - executed when no execptions occur
finally: # optional
# finally block - executed in any case
Check the try/except
special page.
Matching system#
This section describes how python describes to which except
block an occured exception should lead to.
The rule is easy: if an exception occurs in an except
block, python looks for the first except
block that matches the raised exception or any of its ancestors. If there is no corresponding except
blocks, the else
block will be executed, if there is no else
block interpreter stops with an corresponding message.
The following cell demonstrates that ancestors are matched for the child type exceptions and that order matters.
try:
raise ValueError
except Exception:
print("raised Exception")
except ValueError:
print("raised ValueError")
raised Exception
The key feature here is that Exception
catches the raise ValueError
, and since it placed before the specific expcet block for ValueError
, it handles the exception first.
To confirm that order really matters, the following cell shows the same example but reverses the order of ValueError
and Exception
.
try:
raise ValueError
except ValueError:
print("raised ValueError")
except Exception:
print("raised Exception")
raised ValueError
A ValueError
is raised because it comes first.
Duplicates#
You can define any number of except
blocks for the same exception type, but only the first one will be called.
In the following example, even though is declared two codes for the ZeroDivisionError
type exception, only the first one was executed.
try:
1/0
except ZeroDivisionError:
print("First code to handle exception")
except ZeroDivisionError:
print("Second code to handle exception")
First code to handle exception
Exception object#
In the except clause, you can be specify a variable that will hold the instance of the exception that occurred - you must use the syntax except <Exception> as <variable name>
as the result in the corresponding block can implement logic that works with <variable name>
. This variable will refer to the instance of the exception that raised.
The following cell shows how different exceptions pass the corresponding object to the variable of the except
block.
try_functions = [
lambda: 8/0,
lambda: "hello" + 4
]
for fun in try_functions:
try:
fun()
print("no error")
except Exception as e:
print(type(e))
print("error type:", e)
<class 'ZeroDivisionError'>
error type: division by zero
<class 'TypeError'>
error type: can only concatenate str (not "int") to str
The next code shows that the variable contains exactly the object that was used in the raise
statement.
my_error = ValueError("This is some simple error")
try:
raise my_error
except Exception as e:
print(e is my_error)
True
From sys#
In the sys
built-in python module, there are two functions, sys.exception()
and sys.exc_info()
, which can also provide information about exceptions that have occurred. See the corresponding section of the official documentation for more information.
The following cell shows that sys.exception
returns exactly the same object of the exception.
import sys
try: 9/0
except Exception as e: print(sys.exception() is e)
True
sys.exc_info
is an old fashioned function that returns a tuple with different compoments of the exception.
try: "10" + 10
except: print(sys.exc_info())
(<class 'TypeError'>, TypeError('can only concatenate str (not "int") to str'), <traceback object at 0x799ef7ff6200>)
Traceback#
Traceback is information about where in the code an exception occurred. It can be extracted from the exception instance using __traceback__
attribute. Practically you have to use traceback.format_exception
to prepare traceback to the view as it is printed to the output in the python programm. Read more about traceback objects on the corresponding page of the official documentation.
The following cell stores the exception instance that will be used as an example.
try:
10/0
except Exception as e:
val = e
It holds few attributes that actually hold all the information from which a typical traceback message can be constructed.
traceback = val.__traceback__
print(traceback.tb_frame)
print(traceback.tb_lineno)
print(traceback.tb_lasti)
<frame at 0x799ef7facca0, file '/tmp/ipykernel_8011/2685439381.py', line 4, code <module>>
2
8
The following cell shows the use of the traceback.format_exception
function to construct a typical traceback message.
import traceback
ans = traceback.format_exception(type(val), val, val.__traceback__)
print("".join(ans))
Traceback (most recent call last):
File "/tmp/ipykernel_8011/2685439381.py", line 2, in <module>
10/0
~~^~
ZeroDivisionError: division by zero