python高级之 —— 异常处理

一、异常

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

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

错误分为两种:

1.语法错误(这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正)
#语法错误示范一
if 
#语法错误示范二
def test:
    pass
#语法错误示范三
class Foo
    pass
#语法错误示范四
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:pass
Foo.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:  缩进错误
def func():
  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)

 

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

二、异常处理

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

  1. 语法检测异常
  2. 运行时异常(解析执行期间发生)

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

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

Age=10
while True:
    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:
    被检测代码(可能发出错误)
(可以通过给异常去别名来获取异常的对象,对象中包含了错误信息)
except Exception:
  try中一旦检测到异常,就执行这个位置的逻辑(代码)
也可以先捕获能够明确的异常类型,最后捕获万能异常类型

 

try:
    被检测的代码块(可能发出错误的代码)

except 异常类型:(except可以有多个)
    try中一旦检测到异常,就执行这个位置的逻辑(代码)

else :(当没有发生异常会执行else,其只能在except后)

finally:

try:
    被检测的代码块(可能发出错误的代码)

except 异常类型:(except可以有多个)
    try中一旦检测到异常,就执行这个位置的逻辑(代码)

finally :(无论是否发生异常,最后都会执行finally中代码)

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

import io

try:
    print("start")
    f = open("1.今日内容","rt",encoding="utf-8")
    f.read()
    print("end")
except FileNotFoundError:
    print("文件路径错误...")
except io.UnsupportedOperation:
    print("文件不能被写入....")
finally:
    f.close()

print(f.closed)
finally的使用场景

 

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

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

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

主动发出异常:

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

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

 

自定义异常:

class EgonException(BaseException):
    def __init__(self,msg):
        self.msg=msg
    def __str__(self):
        return self.msg

try:
    raise EgonException('类型错误')
except EgonException as e:
    print(e)

---------------------------------------------------------
class LoginException(Exception):
    pass

def login():
    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两个属性格式化异常信息

class SlopOverError(Exception):
    def __init__(self,num,msg):
        self.num=num
        self.msg=msg

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

class Integer:
    @staticmethod
    def input():
        while True:
            num=input("-------->").strip()
            try:
                num=int(num)
                Integer.verifySlopOver(num)
                return num
            except ValueError as e:
                print(e)
            except SlopOverError as e:
                print(e)
    @staticmethod
    def verifySlopOver(num):
        if num<-2147483648 or num>2147483647:
            raise SlopOverError(num,"ErrorMsg:")

res=Integer.input()
print(res)
自定义一个Integer类

 

posted @ 2019-05-29 11:24  呔!妖精。。。  阅读(202)  评论(0编辑  收藏  举报