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
KeyboardInterruptexception.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
trystatement works ?the
try claus(betweentryandexcept) are executed.—-> no exception occurs
exceptclaus are skipped and the execution oftryis finished.—-> an exception occurs
the rest of
tryclaus is skipped—–> the exception type matches the exception named after the
exceptkeywordExecute the exception claus and the execution of
tryis finished.—–> the exception type doesn’t match any name.
it is passed to the outer
trystatement—–> if there is an outer
trystatementThe process repeated
—–> if there does not exist an outer
trystatementThe 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
Exceptioncan be used as an ExceptionA class in an
exceptclause 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.exceptcan 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...exceptclaus have an optionalelse, must follow all except clauses, it is executed iftrydo not raise any exception. useelseinstead of nestedtry...exceptcan avoid catch exceptions which are not raised by codes intry1
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
tryclaus, even it is in a function call (even indirectly)1
2
3
4
5
6
7
8
9def this_fails():
x = 1/0
...
try:
this_fails()
except ZeroDivisionError as err:
print('Handling run-time error:', err)
...
Handling run-time error: division by zero8.4. Raising Exceptions
The
raisestatement allows the programmer to force a specified exception to occur.
raisemust 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
raisestatement allows an optionalfromwhich enables chaining exceptions. This can be useful when transform exceptions
1 | def func(): |
Exception chaining happens automatically when an exception is raised inside an
exceptorfinallysection. Exception chaining can be disabled by usingfrom Noneidiom: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
Exceptionclass, 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
finallyclaus is intended to define clean-up actions that must be executed under all circumstances.
how
finallyworks 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
finallyclause includes areturnstatement, the returned value will be the one from thefinallyclause’sreturnstatement, not the value from thetryclause’sreturnstatement.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:
print("division by zero!")
else:
print("result is", result)
finally:
print("executing finally clause")
...
divide(2, 1)
result is 2.0
executing finally clause
divide(2, 0)
division by zero!
executing finally clause
divide("2", "1")
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
finallyclause 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.