Python: 学习系列之八:异常的处理

系列

异常如何捕获

当函数内发生异常,异常实例对象对被抛给该函数的调用者,如果该函数的调用者没有捕获和处理,则继续抛给上一层的调用者,这样一直向上抛,最后会被Python解释器捕获。

在异常实例对象被向上抛的过程中,可以选择合适的层对异常实例对象进行捕获和处理,而不需要在每一层进行捕获和处理。

错误的详细信息

  1. Traceback,它指的是异常调用堆栈的跟踪信息,其中列出了程序中的相关行数
  2. 对应的异常类对象的名称,以及异常的错误信息
print(1/0)

# PS C: \Users\cong.wu\Desktop\Test > python exception.py
# Traceback(most recent call last):
#   File "exception.py", line 1, in < module >
#   print(1/0)
# ZeroDivisionError: division by zero

try-except-else-finally

"""
    1. python内置了很多异常类对象,所有内置异常类对象的基类是Exception
    2. 使用try-except语句来捕获和处理异常
    3. 如果有多个except来处理异常,则按顺序匹配得第一个异常将会被处理并返回
"""

try:
    1/0
except TypeError:
    print("type error")
except ZeroDivisionError:
    print("0 can't be as a divisor")
except (TypeError, ZeroDivisionError):  # 这里可以使用元组的形式,有顺序的。
    print("0 can't be as a divisor")
except ZeroDivisionError as err:
    print(err)
except Exception:  # 捕获所有的异常
    print(err)
finally:
    print('释放资源') #一定会被执行的代码,不论是否会报错,通常为释放资源,比如:关闭文件,关闭网络连接等

"""
    不发生异常时,执行else语句,例子如下
"""
while True:
    try:
        x = int(input('请输入一个整数:'))
    except Exception as ex:
        print('无效的输入,请再次输入:')
    else:
        break

使用raise手动抛出异常

def getInt():
    try:
        return int(input('请输入一个整数'))
    except:
        raise #这里不想处理,就直接向上抛出
        # raise ValueError("输入错误") #可以处理一下,抛出一个新的错误


try:
    x = getInt()
except Exception as ex:
    print(ex)
else:
    print("您输入正确的整数是:%i" % x)
finally:
    print("结束!")

自定义异常

"""
    自定义异常必须继承于Exception或Exception的子类
"""


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


try:
    raise MyException("抛个错")
except MyException as err:
    print(err.msg)  # 抛个错

查看异常详细信息

"""
    在捕获异常实例对象后,可以通用标准库中的sys模块中的函数exc_info以获取异常的相关信息
    该函数返回值是一个包含三个元素的元组,分别表示:异常的类型,异常的错误信息,异常的跟踪信息
"""
import sys
import traceback
try:
    1/0
except Exception as err:
    ex_type, ex_value, ex_traceback = sys.exc_info()
    print(ex_type)  # <class 'ZeroDivisionError'>
    print(ex_value)  # division by zero
    print(ex_traceback)  # <traceback object at 0x00000189BFD95048>
    tb =traceback.extract_tb(ex_traceback)
    print(tb)  # [<FrameSummary file exception.py, line 57 in <module>>]
    for filename,linenum,funcname,source in tb:
        print(filename) #exception.py
        print(linenum)  # 57
        print(funcname)  # <module>
        print(source)  # 1/0
    

with语句


"""
    1. 如果一个类对象实现了特殊方法__enter__() 和__exit__(),那么就称这个类对象遵守了上下文管理协议,同时,这个类对象的实例对象被称为上下文管理器。
    2. with语句会让上下文管理器创建一个运行时上下文,当进入运行时上下文时自动调用特殊方法__enter__(),当离开运行时上下文时自动调用特殊方法__exit__().
    3 .with语句的语法格式为:
        with 上下文表达式 [as 变量]:
            with 语句体
    4. __exit__()始终会被执行,它相当于finally.
"""


class MyContextManager(object):
    def __enter__(self):
        print('特殊方法__enter__被调用')
        return self  # 这里的值会返回给mcm

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('特殊方法__exit__被调用')
        return False  # 如果这里返回True,则下面1/0的异常不会被抛出,否则会被抛出。所以这里最好是不写,默认返回False,另加try-except来处理

    def do_sth(self):
        print('方法do_sth()被调用')
        print(1/0)  # 如果这里会抛出异常,那__exit__()方法里的三个参考会自动赋值


with MyContextManager() as mcm:
    mcm.do_sth()
    # 特殊方法__enter__被调用
    # 方法do_sth()被调用
    # 特殊方法__exit__被调用

"""
    这是推荐的做法,当with语句体中产生异常,并且特殊方法__exit__()没有返回True时,为了让程序继续执行,可以使用try-except对抛出的异常进行捕获和处理
"""

try:
    with MyContextManager() as mcm:
        mcm.do_sth()
        # 特殊方法__enter__被调用
        # 方法do_sth()被调用
        # 特殊方法__exit__被调用
except Exception as err:
    print(err)
    #   Traceback(most recent call last):
    #   File "exception.py", line 75, in <module>
    #     mcm.do_sth()
    #   File "exception.py", line 71, in do_sth
    #     print(1/0)  # 如果这里会抛出异常,那__exit__()方法里的三个参考会自动赋值
    # ZeroDivisionError: division by zero
发布了105 篇原创文章 · 获赞 46 · 访问量 21万+

猜你喜欢

转载自blog.csdn.net/wucong60/article/details/94320504
今日推荐