Python3 错误和异常
968字约3分钟
2024-08-10
即便 Python
程序的语法是正确的,在运行它的时候,也有可能发生错误。运行期检测到的错误被称为异常
大多数的异常都不会被程序处理,都以错误信息的形式展现在这里:
>>> 10 * (1/0) # 0 不能作为除数,触发异常
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ZeroDivisionError: division by zero
>>> 4 + spam*3 # spam 未定义,触发异常
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'spam' is not defined
>>> '2' + 2 # int 不能与 str 相加,触发异常
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str
异常以不同的类型出现,这些类型都作为信息的一部分打印出来: 例子中的类型有 ZeroDivisionError
,NameError
和 TypeError
错误信息的前面部分显示了异常发生的上下文,并以调用栈的形式显示具体信息
异常处理
try/except
异常捕捉可以使用 try/except
语句
while True:
try:
x = int(input("请输入一个数字: "))
break
except ValueError:
print("您输入的不是数字,请再次尝试输入!")
try
语句按照如下方式工作
首先,执行
try
子句(在关键字try
和关键字except
之间的语句)如果没有异常发生,忽略
except
子句,try
子句执行后结束如果在执行
try
子句的过程中发生了异常,那么try
子句余下的部分将被忽略。如果异常的类型和except
之后的名称相符,那么对应的except
子句将被执行如果一个异常没有与任何的
except
匹配,那么这个异常将会传递给上层的try
中
try/except...else
try/except
语句还有一个可选的 else
子句,如果使用这个子句,那么必须放在所有的 except
子句之后
else
子句将在 try
子句没有发生任何异常的时候执行
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except IOError:
print('cannot open', arg)
else:
print(arg, 'has', len(f.readlines()), 'lines')
f.close()
使用 else
子句比把所有的语句都放在 try
子句里面要好,这样可以避免一些意想不到,而 except
又无法捕获的异常
try-finally 语句
try-finally
语句无论是否发生异常都将执行最后的代码
# 捕获所有异常
try:
f = open("D:/py-project/abc.txt", "r", encoding="UTF-8")
except Exception as e:
print(e)
f = open("D:/py-project/abc.txt", "w", encoding="UTF-8")
finally:
print("不管有没异常,finally 我都会执行")
f.close()
# [Errno 2] No such file or directory: 'D:/py-project/abc.txt'
# 不管有没异常,finally 我都会执行
抛出异常
Python
使用 raise
语句抛出一个指定的异常
raise语法格式如下
raise [Exception [, args [, traceback]]]
以下实例如果 x
大于 5
就触发异常
x = 10
if x > 5:
raise Exception('x 不能大于 5。x 的值为: {}'.format(x))
用户自定义异常
你可以通过创建一个新的异常类来拥有自己的异常。异常类继承自 Exception
类,可以直接继承,或者间接继承
>>> class MyError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
>>> try:
raise MyError(2*2)
except MyError as e:
print('My exception occurred, value:', e.value)
My exception occurred, value: 4
>>> raise MyError('oops!')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
__main__.MyError: 'oops!'
定义清理行为
try
语句还有另外一个可选的子句,它定义了无论在任何情况下都会执行的清理行为
>>> try:
... raise KeyboardInterrupt
... finally:
... print('Goodbye, world!')
...
Goodbye, world!
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
KeyboardInterrupt
以上例子不管 try
子句里面有没有发生异常,finally
子句都会执行
如果一个异常在 try
子句里(或者在 except
和 else
子句里)被抛出,而又没有任何的 except
把它截住,那么这个异常会在 finally
子句执行后被抛出