一、异常

异常就是代码执行过程中出错的信号,异常有三部分:追踪信息,异常类型,异常的值

在python中,错误出发的异常通常长这样


错误分为两种:

1.语法错误(这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正)



#语法错误示范一

if

#语法错误示范二

deftest:pass

#语法错误示范三

classFoopass

#语法错误示范四

print(haha#SyntaxError: invalid syntax

语法错误 SyntaxError: invalid syntax

2.逻辑错误



#TypeError: int类型不可迭代

for i in 3:pass #TypeError: 'int' object is not iterable

#ValueError

num=input(">>:") #输入hello

int(num) #ValueError: invalid literal for int() with base 10: 'hello'

#NameError

aaa #NameError: name 'aaa' is not defined

#IndexError

l=['egon','aa']

l[3] #IndexError: list index out of range

#KeyError

dic={'name':'egon'}

dic['age'] #KeyError: 'age'

#AttributeError

class Foo:passFoo.x#AttributeError: type object 'Foo' has no attribute 'x'

#ZeroDivisionError:无法完成计算

res1=1/0

res2=1+'str' #ZeroDivisionError: division by zero

逻辑错误

在python中,不同异常可以用不同的类型去标识,一个异常标识一种错误。

常见的异常

#SyntaxError: 语法错误

g= #SyntaxError: invalid syntax

#NameError:名字不存在

age #NameError: name 'age' is not defined

#FileNotFoundError:路径错误

open("asa") #FileNotFoundError: [Errno 2] No such file or directory: 'asa'

#ValueError:文件已关闭,无法继续读写

f = open("1.今日内容")

f.close()

f.read()#ValueError: I/O operation on closed file

#io.UnsupportedOpration: 读写模式错误,不能写入数据

f = open("1.今日内容",mode="rt",encoding="utf-8")

f.write("123") #io.UnsupportedOperation: not writable

#ValueError:数据的值错误导致

int("abc") #ValueError: invalid literal for int() with base 10: 'abc'

#IndentationError: 缩进错误

deffunc():print(1)print(2) #IndentationError: unexpected indent

#IndexError: 索引不存在

li =[]

li[1] #IndexError: list index out of range

#KeyError: key不存在

dic ={}

dic["name"] #KeyError: 'name'

当异常发生时,解释器会打印异常的详细信息,并终止程序执行

排查错误的方法:1.定位到错误发生的位置,查看追踪信息

I.自定义代码,且没有调用任何内置模块或方法 ,那么错误位置一定在最后一行

II.调用了其他模块的方法

内置模块:一定是调用时出错

第三方:有可能出错,按追踪信息点击排查2.查看异常类型 (如IndexError)3.查看异常的值 (如list index out of range)

异常一旦发生就会导致程序终止,这对于用户而言体验极差。所以我们需要有一种机制能够防止程序因为异常而终止

二、异常处理

之前讲到错误分为两类,同样异常可由发生时间不同分为两类:

语法检测异常

运行时异常(解析执行期间发生)

为保证程序的健壮性与容错性,我们需要对异常进行处理

若错误发生的条件时可预知的,我们需要用if进行处理(在错误发生前预防)

Age=10

whileTrue:

age=input('>>:').strip()if age.isdigit(): #只有在age为字符串形式的整数时,下列代码才不会出错,该条件是可预知的

age=int(age)if age ==Age:print('you got it')break

若不可预知,则用try...except(在错误发生之后处理)

try:

被检测的代码块(可能发出错误的代码)except异常类型:(异常类只能用来处理指定的异常情况,如果非指定异常则无法处理。except可以有多个,即多分支)

try中一旦检测到异常,就执行这个位置的逻辑(代码)

1:把错误处理和真正的工作分开来

2:代码更易组织,更清晰,复杂的工作任务更容易实现

3:毫无疑问,更安全了,不至于由于一些小的疏忽而使程序意外崩溃了

万能异常 Exception 类(可能会导致程序既不报错也不正常运行,无法定位错误位置)try:

被检测代码(可能发出错误)

(可以通过给异常去别名来获取异常的对象,对象中包含了错误信息)exceptException:

try中一旦检测到异常,就执行这个位置的逻辑(代码)

也可以先捕获能够明确的异常类型,最后捕获万能异常类型

try:

被检测的代码块(可能发出错误的代码)except异常类型:(except可以有多个)

try中一旦检测到异常,就执行这个位置的逻辑(代码)else :(当没有发生异常会执行else,其只能在except后)

finally:

try:

被检测的代码块(可能发出错误的代码)except异常类型:(except可以有多个)

try中一旦检测到异常,就执行这个位置的逻辑(代码)finally :(无论是否发生异常,最后都会执行finally中代码)

finally的使用场景  可以用finally来执行一些清理操作  类似__del__



importiotry:print("start")

f= open("1.今日内容","rt",encoding="utf-8")

f.read()print("end")exceptFileNotFoundError:print("文件路径错误...")exceptio.UnsupportedOperation:print("文件不能被写入....")finally:

f.close()print(f.closed)

finally的使用场景

1.如果能明确知道异常发生原因 就不要产生异常 使用if判断等方式

2.不知道异常发生的原因 但是知道异常的类型 那就明确捕获该类型的异常

3.不知道发生原因 也不知道 异常的类型 可以使用万能异常 但是一定要打印异常消息

主动发出异常:

try:raise TypeError('类型错误')exceptException as e:print(e) #类型错误

#raise 关键字,后面跟任意Exception类型的子类

自定义异常:



classEgonException(BaseException):def __init__(self,msg):

self.msg=msgdef __str__(self):returnself.msgtry:raise EgonException('类型错误')exceptEgonException as e:print(e)---------------------------------------------------------

classLoginException(Exception):pass

deflogin():

name= input("username:").strip()

pwd= input("password:").strip()if name == "blex" and pwd == "123":print("登录成功!")else:raise LoginException("用户名或密码不正确....")

login()

自定义异常栗子



--该类有个input方法,调用该方法一定会得到一个合法的数字(非数字为不合法,越界为不合法)----如果是非数字不合法,需要打印不合法消息,然后用户需要重新输入-- 如输入'abc',不合法消息就为:invalid literal for int() with base 10: 'abc'----->ValueError----如果是越界不合法,需要打印不合法消息,然后用户需要重新输入-- 如输入'2147483648',不合法消息就为:ErrorMsg:2147483648 -越界

提示:1)该方法需要捕获并处理两次异常(内置异常ValueError,自定义异常SlopOverError)2)该方法运用到递归方式处理更简单,如果用不到递归也可以-- 该类有个verifySlopOver方法,可以判断传入的数字是否越界(非-2147483648 ~2147483647为越界)----如果数字越界,会主动抛出自定义SlopOverError异常,并传入数字和异常消息

自定义异常SlopOverError类--该类需要重写__init__方法----有num、msg两个参数,num是数字类型的数,msg是字符串类型的异常消息--该类需要重写__msr__方法----通过num、msg两个属性格式化异常信息

自定义异常SlopOverError类--该类需要重写__init__方法----有num、msg两个参数,num是数字类型的数,msg是字符串类型的异常消息--该类需要重写__str__方法----通过num、msg两个属性格式化异常信息classSlopOverError(Exception):def __init__(self,num,msg):

self.num=num

self.msg=msgdef __str__(self):return "%s %s -- 越界"%(self.msg,self.num)classInteger:

@staticmethoddefinput():whileTrue:

num=input("-------->").strip()try:

num=int(num)

Integer.verifySlopOver(num)returnnumexceptValueError as e:print(e)exceptSlopOverError as e:print(e)

@staticmethoddefverifySlopOver(num):if num2147483647:raise SlopOverError(num,"ErrorMsg:")

res=Integer.input()print(res)

自定义一个Integer类