import sys
try:
SOME CODE
except (exception1, exception2):
SOME CODE
except EXCEPTION as err:
print(err)
except:
print('Error: ', sys.exc_info()[0])
raise
else:
SOME CODE
finally:
SOME CODE

Errors 分为两种:语法错误和异常。
语法错误
>>> while True print('Hello world') # while 后面少了 :
File "<stdin>", line 1
while True print('Hello world')
^
SyntaxError: invalid syntax
出现了语法错误,只能回到源文件去将语法修正
异常
>>> 4 + spam*3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'spam' is not defined
异常则可以通过 try
语句来处理;
Python 内建异常 Built-in Exceptions
异常处理
# 让用户不断输入,直到得到一个数字,或按 Ctrl-C 退出
>>> while True:
... try:
... x = int(input("Please enter a number: "))
... break
... except ValueError:
... print("Oops! That was no valid number. Try again...")
...
用户按
Ctrl-C
会触发异常KeyboardInterrupt
try
异常处理执行过程:
- 执行 try 语句(位于
try
和except
之间的语句)- 没有异常发生 --> 跳过
except
语句,并进行执行后面的语句 - 一个异常发生 --> 跳过
try
中异常后面的语句- 如果发生的异常与
except
后面的异常批准,执行该except
语句 - 如果没有匹配的异常,则抛出该异常,如果没有外部其他
try
语句处理,程序中止,显示异常
- 如果发生的异常与
- 没有异常发生 --> 跳过

except
后面可以带多个 handlers
... except (RuntimeError, TypeError, NameError):
... pass
子类(从父类中衍生出的类)的异常可以被父类捕捉
# 打印 B C D
class B(Exception):
pass
class C(B):
pass
class D(C):
pass
for cls in [B, C, D]:
try:
raise cls()
except D: # 如果这三个 except 的顺序改成 B C D,将打印 B B B
print("D")
except C:
print("C")
except B:
print("B")
最后一个 except 后面可以不带 handler/exception name,这样讲捕捉任何异常
慎用!因为这种做法可能会导致程序 bug 难以找出;更好的做法是打印出异常信息并再次抛出异常
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except OSError as err: # 注意只要有一个异常实例,可以打印出异常参数(信息)
print("OS error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
raise
The except clause may specify a variable after the exception name. The variable is bound to an exception instance with the arguments stored in
instance.args
. For convenience, the exception instance defines__str__()
so the arguments can be printed directly without having to reference.args
. One may also instantiate an exception first before raising it and add any attributes to it as desired.
try...except
语句还可以带 else
语句; else
要位于所有 except
后面;当没有异常发生时,执行 else
语句
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except OSError:
print('cannot open', arg)
else:
print(arg, 'has', len(f.readlines()), 'lines')
f.close()
else
语句的代码适用于 try
语句必须正常执行后才能执行的代码(正常打开文件后,才打印文件内容);
不把 else
的代码放进 try
是要避免异常是由不是本意要保护的代码造成的
raise
raise
用于强制抛出异常;
raise
带的参数应是异常实例或 Exception
的子类;
如果后面带的是子类, Python 会隐含地初始化它: raise ValueError
==》 raise ValueError()
>>> raise NameError('HiThere')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: HiThere
或者再次抛出异常
>>> try:
... raise NameError('HiThere')
... except NameError:
... print('An exception flew by!')
... raise
...
An exception flew by!
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
NameError: HiThere
用户自定义的异常
用户自定义异常就是定义定义直接或间接继承 Exception
的子类;
自定义的异常应尽可能的简单,仅包含所需要的异常参数;
如果一个模块包含多个异常,通常是先定义一个基础的异常,再衍生出其他具体的异常;
class Error(Exception):
"""Base class for exceptions in this module."""
pass
class InputError(Error):
"""Exception raised for errors in the input.
Attributes:
expression -- input expression in which the error occurred
message -- explanation of the error
"""
def __init__(self, expression, message):
self.expression = expression
self.message = message
class TransitionError(Error):
"""Raised when an operation attempts a state transition that's not
allowed.
Attributes:
previous -- state at beginning of transition
next -- attempted new state
message -- explanation of why the specific transition is not allowed
"""
def __init__(self, previous, next, message):
self.previous = previous
self.next = next
self.message = message
- 大多数异常的名称都以 Error 结尾
Clean-up Actions 清理工作
try
语句还可以带另一个语句 -- finally
,无论有没有异常发生,finally
都会执行。
>>> try:
... raise KeyboardInterrupt
... finally:
... print('Goodbye, world!')
...
Goodbye, world!
KeyboardInterrupt
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
虽然 finally
语句可以用于释放资源(文件或网络连接),但是还有一种更好的方法就是使用 with
with open("myfile.txt") as f:
for line in f:
print(line, end="")
但代码块执行结束时,文件资源将自动释放;支持 with
语句的对象都会在文档表明
网友评论