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.jpg
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语句处理,程序中止,显示异常
- 如果发生的异常与
- 没有异常发生 --> 跳过
try_clause.jpg
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 语句的对象都会在文档表明









网友评论