异常介绍和捕获异常及抛异常和自定义异常

异常介绍

1. 什么是异常

本节以Python为例:
异常Exception:代码写错了,解释器无法运行。只要包括书写上语法上的错误和运行时的错误。

错误从轻到重:拼写检查inspection < 普通information < 警告warning < 运行时错误runtime Error < 异常 Exception < 严重的错误Error < 崩溃

2. 错误栈

def foo():
    print(1/0)
def boo():
    print('hello')
    foo()
boo()
错误跟踪栈 traceback:错误栈展示出错信息:哪一个文件、第几行、出错代码在哪个模块方法下、出错的代码。根据函数的镶嵌和执行顺序,按从早到晚排序。最后是出错类型和描述。

如何排错:看看错误栈的前面的信息,知道从哪个代码开始出错;看看后面的信息,知道哪一句代码出错了;看看最后一句错误类型和描述。

3. 遇到过的错误

  • 变量未声明就调用。 如:
>>> b=1
>>>c=2
>>>print(a)   
 NameError: name 'a' is not defined
  • 语法错误:少写冒号等。
>>>if a>b
 ...    return a

 SyntaxError: invalid syntax
  • 缩进错误:
IndentationError: expected an indented block
  • 索引错误:超出下标范围
>>>[1,2,3][3] 
IndexError: list index out of range
  • 类型错误:调用函数时参数的类型或个数不匹配。
>>>def foo():
...    print(1/0)
...def boo():
...    print('hello')
...    foo()
...boo(1)
TypeError: boo() takes 0 positional arguments but 1 was given
  • 值错误:
>>>int('h') 
 ValueError: invalid literal for int() with base 10: 'h'
  • 零除错误:
>>>1/0  
  ZeroDivisionError: division by zero
  • 递归错误:
 RecursionError:maximum recursion depth exceeded
  • 键错误:
>>>{'key':'value'}['aaa'] 
  KeyError: 'aaa

异常捕获

场景:一个大型项目,业务逻辑复杂。当出现异常错误时,我们并不希望程序终止,希望程序主体功能运行;收集分析错误信息
  try {
        // 有可能抛出异常的代码
    } 
    except (Exception e) {
        // 异常处理
    }
     finally {
        // 无论是否捕获到异常都会执行的程序
    }

示例1 捕获异常

def foo():
    try:
        print(1/0)
    except ZeroDivisionError:
        print('不能除以0')
    finally:
        print('我最后执行')
    print('world')
def boo():
    print('hello')
    foo()
    print('world')
boo()
  1. 捕获异常: try…except…finally
  2. try 括住可能发生问题的语句。偷懒方法try括住程序最外层,但这样捕获后不好定位出错的地方。
  3. except :后面跟异常的类名,如果捕获到这种异常,那么就会执行语句块,执行发生异常后的一些处理,处理比如 用户提示信息、记录日志、业务逻辑。
  4. finally:不管程序正常运行,或是出现某种异常被捕获,在或是出现异常没有被捕获,最终都会执行
  5. 捕获异常应该适当使用,使用过多代码会乱,不用的话错误可能导致程序崩溃带来损失。 场景:捕获数据库操作代码。

示例2

# f = open('demo.txt')
try:
    f = open('demo.txt')
    content = f.read()
    print(content)          # try块里面的变量变成局部变量,注意外部不用引用内部局部变量
except FileNotFoundError:
    print('文件未找到,请检查文件名')
except UnicodeDecodeError:
    print('unicode解码错误')
except Exception as e:  # e = FileNotFoundError()
    print(e)
finally:
    f.close()
  1. try块里面的变量变成局部变量,注意外部不用引用内部局部变量

  2. 如果try块中的代码可能报多种异常,那么多写几个并列的except 语句。

  3. 不知道错误类的类名:可能会出现代码中定义错误之外的未知新错误.使用所有错误类的父类Exception 类来捕获。

  4. finally 场景:打开文件资源,不管有没有出错,最终应该保证关闭文件。

  5. as 把…作为… 。关键字:类似等号赋值,可以写成一行。

抛异常和自定义异常

代码中遇到问题有时主动抛出异常,交给上层函数处理。遇到新问题需要自定义异常。 错误可控,有点小问题就可以主动抛异常 终止程序运行。

class DivisionError(ValueError):    # 自定义异常类
    pass
def foo(num):
    if num == 0:
        # raise Exception
        # raise ValueError('除数不能为0')
        # raise ZeroDivisionError('除数不能为0')
        raise DivisionError('除数不能为0')
    print(10/num)
foo(1)
foo(2)
foo(0)

自定义异常信息,中文或跟项目相关信息。 raise ValueError(‘除数不能为0’)
可以自定义异常类,自定义类可以继承系统内置异常类。
抛异常好处:自定义 把问题集中处理

错误类的父子关系 Exception → ArithmeticError → ZeroDivisionError

你可能感兴趣的:(Python基础)