There are (at least) two distinguishable kinds of errors: syntax errors and exceptions.
8.1. Syntax Errors
a little ‘arrow’ pointing at the earliest point in the line where the error was detected. The error is caused by (or at least detected at) the token preceding the arrow
1
2
3
4
5True 4 False
File "<stdin>", line 1
True 4 False
^
SyntaxError: invalid syntaxFile name and line number are printed so you know where to look in case the input came from a script.
8.2. Exceptions
Errors detected during execution are called exceptions and are not unconditionally fatal
- Exceptions come in different types, and the type is printed as part of the message
- Standard exception names are built-in identifiers (not reserved keywords).
- see more at Built-in Exceptions
8.3. Handling Exceptions
a user-generated interruption is signalled by raising the
KeyboardInterrupt
exception.1
2
3
4
5
6while True:
try:
enter = input("Here is echo system:\n")
print(enter)
except KeyboardInterrupt:
print("You can't get out @_@")1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17Here is echo system:
sdfioaj
sdfioaj
Here is echo system:
^CYou can't get out @_@
Here is echo system:
Here is echo system:
^CYou can't get out @_@
Here is echo system:
Traceback (most recent call last):
File "/Users/rubbish/test/ptest.py", line 3, in <module>
enter = input("Here is echo system:\n")
EOFError
# enter a ^D as EOF to raise another Exception to get out.1
2
3
4
5
6
7
8while True:
try:
enter = input("Here is echo system:\n")
print(enter)
except KeyboardInterrupt:
print("You can't get out @_@")
except:
print('No way!!!')1
2
3
4
5
6
7
8
9
10
11
12
13
14
15Here is echo system:
iowef
iowef
Here is echo system:
No way!!!
Here is echo system:
^CYou can't get out @_@
Here is echo system:
ffffffffffffffffffffffff
ffffffffffffffffffffffff
Here is echo system:
^CYou can't get out @_@
Here is echo system:
No way!!!
zsh: terminated python3 ptest.py1
2$ ps
$ kill PythonPIDHow
try
statement works ?the
try claus
(betweentry
andexcept
) are executed.—-> no exception occurs
except
claus are skipped and the execution oftry
is finished.—-> an exception occurs
the rest of
try
claus is skipped—–> the exception type matches the exception named after the
except
keywordExecute the exception claus and the execution of
try
is finished.—–> the exception type doesn’t match any name.
it is passed to the outer
try
statement—–> if there is an outer
try
statementThe process repeated
—–> if there does not exist an outer
try
statementThe exception becomes an unhandled exception and the program break at the exception line.
1
2
3
4
5
6
7
8print("start")
try:
print('enter try claus')
raise ValueError
print('after ValueError') # this line will never be executed
except ValueError:
print('executing except claus')
print("end")1
2
3
4start
enter try claus
executing except claus
endAn except clause may name multiple exceptions as a parenthesized tuple
1
2except (RuntimeError, TypeError, NameError):
passClass derived from an
Exception
can be used as an ExceptionA class in an
except
clause is compatible with an exception if it is the same class or a base class thereof1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20class B(Exception):
pass
class C(B):
pass
class D(C):
pass
for cls in [B, C, D]:
try:
raise cls()
except D:
print("D")
except C:
print("C")
except B:
print("B")
# This will print BCD
# if the except clauses were reversed (with except B first), it would have printed B, B, B — the first matching except clause is triggered.except
can omit the exception name(s), to serve as a wildcard.- but this may mask an error, use it carefully
- you can reraise the captured exception with
raise
1
2
3
4
5
6import sys
try:
file = open('notexist.txt')
except:
print('Error',sys.exc_info())
raise1
2
3
4
5Error (<class 'FileNotFoundError'>, FileNotFoundError(2, 'No such file or directory'), <traceback object at 0x10ee85040>)
Traceback (most recent call last):
File "/Users/******/test/ptest.py", line 4, in <module>
file = open('notexist.txt')
FileNotFoundError: [Errno 2] No such file or directory: 'notexist.txt'The
try...except
claus have an optionalelse
, must follow all except clauses, it is executed iftry
do not raise any exception. useelse
instead of nestedtry...except
can avoid catch exceptions which are not raised by codes intry
1
2
3
4
5
6try:
f = open('exist')
except FileNotFoundError:
print('file not found')
else:
print(f.read() , end='')exceptions can have arguments, stored in
instance.args
, can be print directly useinstance.__str__()
1
2
3
4
5
6
7ins = Exception ('Hello' , 'world')
argus = ins.args
print(type(argus))
x , y = argus
print(x ,y )
ss = ins.__str__()
print(type(ss) , ss)1
2
3<class 'tuple'>
Hello world
<class 'str'> ('Hello', 'world')If an unhandled exception has argus, they are printed as the last part (‘detail’) of the exception
1
2ins = (Exception('I am an error'))
raise ins1
2
3
4Traceback (most recent call last):
File "/Users/*****/test/ptest.py", line 2, in <module>
raise ins
Exception: I am an errorException handlers can handle exception in
try
claus, even it is in a function call (even indirectly)1
2
3
4
5
6
7
8
9def this_fails():
1/0 x =
...
try:
this_fails()
except ZeroDivisionError as err:
'Handling run-time error:', err) print(
...
Handling run-time error: division by zero8.4. Raising Exceptions
The
raise
statement allows the programmer to force a specified exception to occur.
raise
must be followed with either an exception instance or an exception class (a class that derives fromException
). If an exception class is passed, it will be implicitly instantiated by calling its constructor with no arguments:1
raise ValueError # shorthand for 'raise ValueError()'
8.5. Exception Chaining
The
raise
statement allows an optionalfrom
which enables chaining exceptions. This can be useful when transform exceptions
1 | def func(): |
Exception chaining happens automatically when an exception is raised inside an
except
orfinally
section. Exception chaining can be disabled by usingfrom None
idiom:1
2
3
4
5
6
7
8try:
open('database.sqlite')
except IOError:
raise RuntimeError from None
'''
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
RuntimeError'''see more at Built-in Exceptions
8.6. User-defined Exceptions
User Exceptions should typically be derived from the
Exception
class, either directly or indirectly.
User-defined Exceptions can do anything any other class can do, but are usually kept simple, often only offering a number of attributes that allow information about the error to be extracted by handlers for the exception.
When creating a module that can raise several distinct errors, a common practice is to create a base class for exceptions defined by that module, and subclass that to create specific exception classes for different error conditions:
1
2
3
4
5
6
7
8
9
10
11
12class Error(Exception):
'''base exception class'''
pass
class InputError(Error):
'''special input error'''
def __init__(self ,message):
self.message = message
class OtherError(Error):
'''other errors'''
passMost exceptions are defined with names that end in “Error”, similar to the naming of the standard exceptions.
8.7. Defining Clean-up Actions
finally
claus is intended to define clean-up actions that must be executed under all circumstances.
how
finally
works under different conditions1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17exec try
if Exception occurs during try:
if Exception handled by except:
exec except claus
if NewException occurs during except:
exec finally claus
raise NewException
else:
exec finally claus
else:
exec finally claus
raise unhandled exception
elif try reach a (break , continue , return) statement:
exec finally claus
exec (break or continue or return) statement
else:
exec finally clausIf a
finally
clause includes areturn
statement, the returned value will be the one from thefinally
clause’sreturn
statement, not the value from thetry
clause’sreturn
statement.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22def divide(x, y):
try:
result = x / y
except ZeroDivisionError:
"division by zero!") print(
else:
"result is", result) print(
finally:
"executing finally clause") print(
...
2, 1) divide(
result is 2.0
executing finally clause
2, 0) divide(
division by zero!
executing finally clause
"2", "1") divide(
executing finally clause
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'In real world applications, the
finally
clause is useful for releasing external resources (such as files or network connections), regardless of whether the use of the resource was successful.
8.8. Predefined Clean-up Actions
Some objects define standard clean-up actions to be undertaken when the object is no longer needed, regardless of whether or not the operation using the object succeeded or failed.
Objects which, like files, provide predefined clean-up actions will indicate this in their documentation.