zoukankan      html  css  js  c++  java
  • 异常处理

    一.错误和异常

    在编写程序时,难免会出现错误,而错误一般分为两种

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

    语法错误示范 

     1 #语法错误示范一
     2 if
     3 
     4 #语法错误示范二
     5 def test:
     6     pass
     7 
     8 #语法错误示范三
     9 class Foo
    10     pass
    11 
    12 #语法错误示范四
    13 print(haha
    14 
    15 语法错误示范

    1.2.逻辑错误示范一

    1 #用户输入不完整(比如输入为空)或者输入非法(输入不是数字)
    2 num=input(">>: ")
    3 int(num)

    逻辑错误示范二

    1 #无法完成计算
    2 res1=1/0
    3 res2=1+'str'

    2.什么是异常

    异常就是在程序运行时发生错误的信号,在Python中,错误触发如下

    3.Python中的异常种类

    在Python中不同的异常可以用不同的类型(Python中统一了类于类型,类型即类)去标识,不同的类对象标识不同的异常,一个异常标识一种错误

    Python中常见的异常

     1 'ArithmeticError'  # 计算错误,算法错误
     2 'AssertionError'  # 断言错误,常用于测试
     3 
     4 'AttributeError'  #  属性错误
     5 'BaseException',   # 基本异常
     6 BlockingIOError'  # 阻塞错误
     7  'BrokenPipeError'  # 管道破裂错误
     8  'BufferError'  # 缓冲区错误
     9  'BytesWarning',  # 字节警告
    10 'ChildProcessError',  # 子进程错误
    11 'ConnectionAbortedError'  #  连接终止错误
    12 'ConnectionError',   # 连接错误
    13 'ConnectionRefusedError'  # 连接拒绝错误
    14  'ConnectionResetError',  # 连接重置错误
    15 'DeprecationWarning'  #  废弃警告
    16 'EOFError'  # 文件终止错误
    17 'Ellipsis'  # 省略错误
    18  'EnvironmentError'  # 环境错误
    19 'Exception'  # 异常
    20  'False'  #
    21 'FileExistsError'  #  文件存在 错误
    22 'FileNotFoundError'  # 文件不存在  错误
    23  'FloatingPointError'  # 浮点指针错误
    24  'FutureWarning'  # 关于构造将来会有改变的警告
    25 'GeneratorExit'  # 生成器发生异常来通知退出
    26  'IOError'  #输入/输出操作失败
    27 'ImportError'  # 导入模块/对象失败
    28  'ImportWarning'  # 导入模块/对象警告
    29  'IndentationError',  # 缩进错误
    30 'IndexError'  # 索引错误,序列中没有该索引
    31 'InterruptedError'  # 被中断的错误
    32  'IsADirectoryError'  # 是一个目录错误
    33 'KeyError'  # 映射中没有这个键
    34  'KeyboardInterrupt'  # 用户终端执行(通常输入的是^c)
    35  'LookupError'   # 无效数据查询基类
    36  'MemoryError'  # 内存溢出错误
    37 'NameError'  # 名字错误
    38  'None'  # 空值
    39  'NotADirectoryError'  # 不是目录错误
    40  'NotImplemented'  #  方法没有实现
    41  'NotImplementedError'  # 尚未实现的方法
    42 'OSError'  # 操作系统错误
    43 'OverflowError'  # 旧的关于自动提升为长整型(long)的警告
    44  'PendingDeprecationWarning'  # 关于特性将会被废弃的警告
    45  'PermissionError'  # 权限错误
    46  'ProcessLookupError'  # 进程获取错误
    47  'RecursionError'  # 递归错误
    48  'ReferenceError'  # 弱引用试图访问已经垃圾回收了的对象
    49 'ResourceWarning'  # 资源警告
    50 'RuntimeError'  # 一般运行时的错误
    51  'RuntimeWarning'  # 可疑的运行时的行为警告
    52  'StopAsyncIteration'  # 停止异步迭代错误
    53 'StopIteration'  # 迭代器没有更多的值
    54 ,'SyntaxError'  #   语法错误
    55  'SyntaxWarning'  # 语法警告
    56  'SystemError'  # 系统错误
    57  'SystemExit',   # 系统退出
    58 'TabError'  # Tab和空格键混用
    59  'TimeoutError'  # 时间超时错误
    60  'True'  #
    61  'TypeError'  # 对象类型错误
    62  'UnboundLocalError',   # 访问未初始化的本地变量
    63 'UnicodeDecodeError'  # Unicode解码时的错误
    64 'UnicodeEncodeError'  # Unicode编码时的错误
    65 'UnicodeError'  # Unicode相关的错误
    66  'UnicodeTranslateError'  # Unicode转换时的错误
    67  'UnicodeWarning',  # Unicode警告
    68  'UserWarning'  # 用户代码生成警告
    69 'ValueError'  # 传入无效的cans
    70 'Warning'  # 警告的基类
    71 'WindowsError'  # 系统调用失败
    72  'ZeroDivisionError'  # 除数为0错误
    73  '__build_class__'
    74 '__debug__'
    75 '__doc__'
    76 '__import__',
    77 '__loader__'
    78 '__name__'
    79 '__package__', 
    80 
    81 '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip

    触发异常举例

    触发IndexError

    触发KeyError

    触发ValueError

    二.异常处理

    2.1什么是异常处理?

    Python解释器检测到错误,触发异常,也允许程序员自己触发异常

    程序员编写特定的代码,专门用来捕捉这个异常,这段代码与程序的逻辑无关,与异常处理有关

    如果捕捉成功进入另外一个处理分支,执行你为其定制的逻辑,使程序不会崩溃,这就是异常处理

    2.2为什么要进行异常处理

    Python解释器去执行程序,检测到了一个错误,触发异常,在异常触发后且没有处理的情况下,程序就在当前异常处终止,后面的代码就不会运行了,那么谁会去用一个运行着就突然崩溃的软件

    所以你必须提供一种异常处理机制来增强你程序的健壮性和容错性

    2.3任何进行异常处理?

    首先必须知道,异常是由程序的错误引起的,语法上的错误跟异常处理无关,必须在程序运行钱就修正

    一.使用if判断式

    正常代码示例

    # 第一段代码
    num1 = input('1>>>')  # 输入一个字符串试试
    int(num1)
    # 第二段代码
    num2 = input('2>>>')  # 输入一个字符串试试
    int(num2)
    # 第三段代码
    num3 = input('3>>>')  # 输入一个字符串试试
    int(num1)

    使用if判断进行异常处理

    num1=input('>>: ') #输入一个字符串试试
    if num1.isdigit():
        int(num1) #我们的正统程序放到了这里,其余的都属于异常处理范畴
    elif num1.isspace():
        print('输入的是空格,就执行我这里的逻辑')
    elif len(num1) == 0:
        print('输入的是空,就执行我这里的逻辑')
    else:
        print('其他情情况,执行我这里的逻辑')
    
    #第二段代码
    # num2=input('>>: ') #输入一个字符串试试
    # int(num2)
    
    #第三段代码
    # num3=input('>>: ') #输入一个字符串试试
    # int(num3)
    
    '''
    问题一:
    使用if的方式我们只为第一段代码加上了异常处理,针对第二段代码,你得重新写一堆if,elif等
    第三段,你还得在写一遍,当然了,你说,可以合在一起啊,没错,你合起来看看,你的代码还能被看懂吗???
    而这些if,跟你的代码逻辑并无关系,这就好比你在你心爱的程序中到处拉屎,拉到最后,谁都不爱看你的烂代码,为啥,因为可读性差,看不懂
    
    问题二:
    第一段代码和第二段代码实际上是同一种异常,都是ValueError,相同的错误按理说只处理一次就可以了,而用if,由于这二者if的条件不同,这只能逼着你重新写一个新的if来处理第二段代码的异常
    第三段也一样
    '''
    
    使用if判断进行异常处理

    总结:

    1.if判断式的异常处理只能是针对某一段代码,对于不同的代码段相同类型的错误你需要写重复的if来进行处理。

    2.在你的程序中频繁的写与程序本身无关,与异常处理有关的if,那么你代码的可读性就会变得极其的差。

    3.这是可以解决异常的,只是存在1,2的问题,所以,不能妄下定论if不能用来异常处理

    二:Python为每一种异常定制了一个类型,然后提供了一种特定的语法结构用来进行异常处理

    2.1 基本语法

    try:
        被检测的代码块
    except 异常类型:
        try中一旦检测到异常,就执行这个位置的逻辑
    

    2.2 异常类只能用来处理指定的异常情况,如果非指定的异常类则无法处理

    1 s1 = 'hello'
    2 try:
    3     int(s1)
    4 except IndexError as f:
    5     print(f)

    2.3 多分支

    1 s1 = 'hello'
    2 try:
    3     int(s1)
    4 except IndexError as f:
    5     print(f)
    6 except KeyError as f:
    7     print(f)
    8 except ValueError as f:
    9     print(f)

    2.4 万能异常,在Python中有一个万能异常,Exception,他可以捕获任意异常,即;

    s1 = 'hello'
    try:
        int(s1)
    except Exception as f:
        print(f)

    你可能会说既然有万能异常,那么我直接用上面的这种形式就好了,其他异常可以忽略了

    你说的没错,但是应该分为两种情况去看

    2.4.1。如果你想要的效果是,无论出现什么异常,我们都统一丢弃,或者使用同一段代码逻辑去处理他们,那么,你大胆去做把,只有一个Exception就足够了

    1 s1 = 'hello'
    2 try:
    3     int(s1)
    4 except Exception as f:
    5     print(f)
    6 
    7 #如果你统一使用Exception,没错,是可以捕捉所有异常,但意味着你在处理所有异常时都使用同一个逻辑去处理(这里说的逻辑即当前expect下面跟的代码块)

    2.4.2如果你想要的效果是,对于不同的异常我们需要定制不同的处理逻辑,那么就需要用到多分支了

    1 s1 = 'hello'
    2 try:
    3     int(s1)
    4 except IndexError as f:
    5     print(f)
    6 except KeyError as f:
    7     print(f)
    8 except ValueError as f:

    2.4.3 也可以在多分支后来一个Exception

     1 s1 = 'hello'
     2 try:
     3     int(s1)
     4 except IndexError as f:
     5     print(f)
     6 except KeyError as f:
     7     print(f)
     8 except ValueError as f:
     9     print(f)
    10 except Exception as f:
    11     print(f)

    5.异常的其他机构

     1 s1 = 'hello'
     2 try:
     3     int(s1)
     4 except IndexError as f:
     5     print(f)
     6 except KeyError as f:
     7     print(f)
     8 except ValueError as f:
     9     print(f)
    10 # except Exception as f:
    11 #     print(f)
    12 else:
    13     print('try内代码块没有异常就执行我')
    14 finally:
    15     print('无论异常与否,都会执行该模块,通常是进行清理工作')

    6 主动触发异常

    1 try:
    2     raise TypeError('类型错误')
    3 except Exception as f:
    4     print(f)

    7.自定义异常

     1 class EgonException(BaseException):
     2     def __init__(self,msg):
     3         self.msg = msg 6 
     8 raise EgonException('类型错误')
    

    8.断言

     1 def test():
     2     '一堆逻辑'
     3     res = 1
     4     return 1
     5 res1 = test()
     6 assert  res1 == 1
     7 # 以下的n多代码要跟res1进行下一步处理
     8 # 如果assert  res1 != 1 就会抛出AssertionError,等同于
     9 if res1 != 1:
    10     raise AssertionError

    9.try..except的方式比较if方式的好处

    try...except这种异常处理机制就是取代if那种方式,让你的程序在不牺牲可读性的前提下增强健壮新和容错性。

    异常处理中为每一个异常都定制了异常类型,对于同一种异常,一个except就可以捕捉到,可以同时处理多段代码的异常,无需写多个if判断式,减少了代码,增强了可读性。

     1 # num1=input('>>: ') #输入一个字符串试试
     2 # if num1.isdigit():
     3 #     int(num1) #我们的正统程序放到了这里,其余的都属于异常处理范畴
     4 # elif num1.isspace():
     5 #     print('输入的是空格,就执行我这里的逻辑')
     6 # elif len(num1) == 0:
     7 #     print('输入的是空,就执行我这里的逻辑')
     8 # else:
     9 #     print('其他情情况,执行我这里的逻辑')
    10 
    11 #第二段代码
    12 # num2=input('>>: ') #输入一个字符串试试
    13 # int(num2)
    14 
    15 #第三段代码
    16 # num3=input('>>: ') #输入一个字符串试试
    17 # int(num3)
    18 
    19 try:
    20     #第一段代码
    21     num1=input('>>: ') #输入一个字符串试试
    22     int(num1) #我们的正统程序放到了这里,其余的都属于异常处理范畴
    23     #第二段代码
    24     num2=input('>>: ') #输入一个字符串试试
    25     int(num2)
    26     #第三段代码
    27     num3=input('>>: ') #输入一个字符串试试
    28     int(num3)
    29 except ValueError as e:
    30     print(e)
    31 
    32 再看try...except的牛逼之处

    使用try...except的方式

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

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

    3.更安全,不会因为一些小的疏忽而使程序意外崩溃了。

    四。什么时候使用异常处理。

    try...except应该尽量少用,因为他本身就是你附加给你的程序的一种异常处理的逻辑,与你的主要工作是没有 关系的

    这种东西加多了,会导致你的代码可读性变差

    而且异常处理根本就不是你2b逻辑的擦屁股纸,只有在有些异常无法预知的情况下,才应该加上try...except,其他的逻辑错误应该尽量修正。

  • 相关阅读:
    设计模式(十)外观模式
    设计模式(九)装饰器模式
    设计模式(八)组合模式
    设计模式(七)桥接模式
    设计模式(六)代理模式
    设计模式(五)适配器模式
    linux 安装 node
    LeetCode 335. Self Crossing
    LeetCode 332. Reconstruct Itinerary 最小欧拉路径
    LeetCode 327. Count of Range Sum 区间和的个数
  • 原文地址:https://www.cnblogs.com/YingLai/p/6240535.html
Copyright © 2011-2022 走看看