异常
常见的异常如下,ZeroDivisionError是built-in的关键字,是异常类exception的子类。
>>> 10 * (1/0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
异常的处理:
>>> while True:
... try:
... x = int(input("Please enter a number: "))
... break
... except ValueError:
... print("Oops! That was no valid number. Try again...")
...
try的处理顺序
1,先走try里面的东西,如果没有异常,except 语句就不会执行。
2,try如果发生异常,则剩下的try代码不会被执行,转而执行相应的except name。
3,如果没有对应的except name则异常传递到上一级try语句。
4,如果始终没有try捕获到这个异常,则程序终止并抛出异常。
一个try可以配合多个except。
... except (RuntimeError, TypeError, NameError):
... pass
except name捕获异常的规则:
class B(Exception): #祖类
pass
class C(B): #父类
pass
class D(C): #子类
pass
for cls in [B, C, D]: #打印B C D,和COBOL EVALUATE一样,配合最前面的WHEN。
try:
raise cls()
except D: #子类不能捕获父类。
print("D")
except C:
print("C")
except B:
print("B")
如果改成以下 则打印B B B,即except父类可以捕获子类异常。
for cls in [B, C, D]:
try:
raise cls()
except B:
print("B")
except C:
print("C")
except D:
print("D")
没有name 的except相当于COBOL的other,接受所有异常。但通常我们只打印一些信息后然后raise再次抛出此异常让别处捕获。
except:
print("Unexpected error:", sys.exc_info()[0])
raise
raise 可以抛出某个具体的异常,如:raise NameError(‘HiThere’)
else子句
else是可选 ,必须写在所有except的后面,当try没有任何异常时才执行else。应当把可能异常的代码写在try中,其余代码放在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()
finally子句
用于清理工作(包括清理网络,数据库连接)。
finally是整个try最后执行的,而且一定会执行,不管理是否有异常。执行完finally后如果try中有异常没被捕获到,则会自动抛出该异常。
>>> def 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 #无异常,走else
executing finally clause #无论有无异常,最后才执行finally
>>> divide(2, 0)
division by zero!
executing finally clause #有异常且被捕获到,同样是最后执行finally
>>> divide("2", "1")
executing finally clause #有异常且没被捕获,不走else,最后执行finally后,再次自动抛出此异常。
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'
with关键字
有些对象内置有预定义的清理工作,即封装好的try+finally
for line in open("myfile.txt"): #这代码执行完后,文件一直处在打开状态
print(line, end="")
with open("myfile.txt") as f: #with关键字使得这段代码执行后文件是自动关闭的
for line in f:
print(line, end="")