错误和异常
程序中的错误分为语法错误和逻辑错误
语法错误: 是指软件的编写不符合语法的语法规定,导致无法被编译器解释或者编译。这些错误必须通过修正程序才能正常运行。
逻辑错误: 程序运行以后出现的错误就是逻辑错误,逻辑错误可能有雨外界条件引发的,也有可能是由于程序本身设计不严谨导致的。
常见的异常及其描述
类名 | 描述 |
---|---|
Exception | 所有异常的基类 |
SyntaxError | 发生语法错误异常类 |
FileNotFoundError | 未找到指定文件或者目录时引发 |
NameError | 未找到指定名称的变量时引发 |
ZeroDivisionError | 除数为零时异常 |
IndexError | 当使用超出列表范围的索引时引发 |
KeyError | 当使用映射不存在的键时引发 |
AttributeError | 当尝试访问未知对象属性时引发 |
TypeError | 当试图在使用a类型的场合使用b类型时引发 |
下面对几种常见的异常进行介绍:
1.SyntaxError 语法错误
if条件后面不写冒号(:)
>>> if 2>1
File "<stdin>", line 1
if 2>1
^
SyntaxError: invalid syntax
2.NameError
尝试访问一个未声明的变量
>>> print(abc)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'abc' is not defined
3.ZeroDivisionError
当除数为零时引发
>>> 2/0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
4.IndexError
访问序列中不存在的索引
>>> mylist = [0]
>>> mylist[1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
5.KeyError
使用映射中不存在的键
>>> mydict = {'name':'xiaoqing','age':28}
>>> mydict[gender]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'gender' is not defined
6.AttributeError
尝试访问未知对象的属性
class Car(object):
pass
car = Car()
car.color = "黑色"
print(car.color)
print(car.name)
异常信息:
Traceback (most recent call last):
File "<stdin>", line 6, in <module>
print(car.name)
AttributeError: 'Car' object has no attribute 'name'
上述例子中,Car类并没有定义任何属性和方法,在创建类的实例后动态的引用实例添加了color属性,然后访问color和name属性时出现上面的错误信息。上述异常信息表明访问了不存在的name属性
7.TypeError
试图将与变量类型不相符的值赋值给变量
>>> i = 5
>>> print("i的值是:"+5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: must be str, not int
是不是上面的错误我们也经常踩坑呢?
异常捕获
1.try-except语句
格式如下:
try:
可能出现错误的代码
……
except [错误类型]:
出错后执行的处理语句
……
说明:try语句后面是可能出错的代码,except语句后面是捕获的异常类型,并指明捕获到异常后的处理方法。
try-except语句的工作方式:
1,首先执行try子句,即在try和except之间的代码
2,如果try子句没有发生异常,则忽略except后面的子句
3,如果try子句发生异常,则忽略该子句的剩余语句,此时有两种情况:
(1),如果发生的异常类型与except后指定的异常类型一致,则执行except子句,然后继续执行try-except语句后面的代码。
(2),如果发生的异常类型与except后指定的异常类型不一致,则该异常会被抛到上一级代码,由上一级代码处理。如果最终都没得到处理,就会使用默认的处理方式:系统崩溃,终止运行,并显示提示信息。
不推荐的两点做法:
(1),异常处理的主要目的是为了防止因外部环境的变化导致的程序无法控制的错误,而不是应该用于处理程序的设计错误,所以将所有的代码都用try语句包含起来的做法是不对的。
(2),捕获异常后需要作出对应的处理,如果在异常后用pass直接忽略掉,会隐藏掉导致程序出错的原因,不利于程序的正常运行和维护,也是不推荐的。
else子句
else子句不仅可以与if和循环语句配合使用之外,还可以与try-except语句配合使用,表示当try子句没有出现错误时执行的语句。
格式如下:
try:
可能出错的语句
……
except:
出错后执行的语句
……
else:
未出错执行的语句
……
finally子句
finally子句与try语句联合使用,表示无论try语句是否出错都会执行的语句。
格式如下:
try:
可能出错的语句
……
finally:
无论是否出错都会执行的语句
……
在实际开发中,finally子句做一些善后工作。但在使用finally子句时需要注意的是:
(1),如果在finally子句引发了异常,则该异常无法捕获
(2),如果在finally子句使用return,break,continue语句而终止,则原来的异常也会丢失,并且无法重新引发。