Python异常捕获与抛出以及With语句简介

目录

捕获异常

抛出异常

预定义清理行为with

@contextmanager

@closing

常见异常


Python3使用try ... except [else]来捕获异常,且要求异常必须继承Exception 类。所有Built-in异常都继承自这个类。

捕获异常

使用 sys.exc_info 和 sys.last_traceback(包含的内容与 sys.exc_info() 相同,但它主要用于调试)可获取异常的详细信息,会返回一个3值元表(type, value, traceback) ,其中:

  • type:捕获到异常的类型名称;

  • value:捕获到异常的实例;

  • traceback:是一个包含stack traceback的对象;可通过traceback模块打印出来:

    • traceback.print_exc():直接打印当前异常信息;

    • traceback.print_tb(...):打印traceback对象信息;

    • traceback.print_exception(*sys.exc_info()):直接打印元素;

try:
    # ...
    raise
except ValueError as err:
    print("Value error: {0}".format(err))
except Exception:
    print(err)
    t,v,tb = sys.exc_info()
    traceback.print_tb(tb)
else: # except可以有多个,但else必须在最后
    # [...没有异常时]
finally:
    # [...总是执行]

# 一个except中捕获多个异常:
except (RuntimeError, TypeError, NameError):

抛出异常

可通过raise抛出build-in异常,也可自定义异常(要直接或间接继承自Exception):

class MyError(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

try:
    raise MyError(2*2)
except MyError as e:
    print('My exception occurred, value:', e.value)

预定义清理行为with

with语句用于保证任何情况下(包括抛出异常时)都能对当前进行访问的资源进行必要的清理工作。

对象要支持with需要满足上下文管理协议:

  • __enter__(self):语句体执行前调用执行,进入与此对象相关的运行时上下文;with语句将将此方法的返回值绑定到语句的AS子句中指定的目标(如果有设置的话);

  • __exit__(self, exc_type, exc_value, traceback):语句体执行完成,退出上下文时执行;

    • 参数描述导致上下文退出的异常。如果上下文运行时没有异常发生,那么三个参数都将置为None。

    • 如果有异常发生,并且该方法希望抑制异常(即阻止它被传播),则它应该返回True。否则,异常将在退出该方法时正常处理。

with context-expression [as target]:
    # with-body

文件访问完成后,总是保证文件被正确关闭了

with open(r'mytest') as tfile:
    for line in tfile:
        print(line)

一个简单示例:

class DummyResource:
    def __init__(self, tag):
        self.tag = tag
        print('Resource [%s]' % tag)
    def __enter__(self):
        print('[Enter %s]: Allocate resource.' % self.tag)
        return self   # 可以返回不同的对象
    def __exit__(self, exc_type, exc_value, exc_tb): #无异常时,后三个参数都为None
        if exc_tb is None:
            print('[Exit %s]: Exited without exception.' % self.tag)
            return True
        else:
            print('[Exit %s]: Exited with exception raised.' % self.tag)
            return False   # 可以省略,缺省的None也是被看做是False

with DummyResource("test") as dr:
    print(dr)   

@contextmanager

编写 __enter__ 和 __exit__ 仍然很繁琐,因此Python的标准库 contextlib 提供了更简单的写法:

from contextlib import contextmanager 
class Query(object): 
    def __init__(self, name):
        self.name = name 
    def query(self):
        print('Query info about %s...' % self.name)
 
@contextmanager
def create_query(name):
    print('Begin')
    q = Query(name)
    yield q
    print('End')

这个装饰器接受一个generator,用 yield 语句把 with ... as var 把变量输出出去,然后with 语句就可以正常的工作了:

with create_query('Bob') as q:
    q.query()

很多时候,我们希望在某段代码执行前后自动执行特定代码,也可以用 @contextmanager实现。

@contextmanager
def tag(name):
    print("<%s>" % name)
    yield
    print("</%s>" % name)
 
with tag("h1"):
    print("hello")
    print("world")

代码的执行顺序是:

  •  with 语句 首先执行 yield 之前的语句,因此打印出 <h1>.

  •  yield 调用会执行 with 语句内部的所有语句,因此打印出 hello 和 world.

  •  最后执行yield之后的语句,打印出 </h1>.

@closing

如果一个对象没有实现上下文,就不能使用 with 语句,但是可以用 closing() 来把对象变为上下文对象。

from contextlib import closing
from urllib.request import urlopen 
with closing(urlopen('https://www.python.org')) as page:
    for line in page:
        print(line)

closing 也是一个经过 @contextmanager 装饰的generator

@contextmanager
def closing(thing):
    try:
        yield thing
    finally:
        thing.close()

它的作用就是把任意对象变为上下文对象,并支持 with语句。

常见异常

- BaseException                     # 所有异常的父类

    - SystemExit                     # 由sys.exit()抛出的异常

    - KeyBoardInterrupt              # 通常由ctrl+c或者Delete抛出的异常

    - GeneratorExit                  # 当生成器被关闭时抛出的异常

    - Exception                      # 

        - StopIteration              # 迭代结束异常

        - StopAsyncIteration         # 由异步迭代的`__anext__()`抛出的异常

        - ArithmeticError            # 各种算数错误引起的异常

            - FloatingPointError     # 浮点数操作错误

            - OverflowError          # 结果超出范围

            - ZeroDivisionError      # 0为除数异常

    - AssertionError                 # assert错误异常

    - AttributeError                 # 属性引用异常

    - BufferError                    # 缓存错误

    - EOFError                       # 读不到数据

    - ImportError                    # import错误

        - ModuleNotFoundError        # 找不多模块

    - LookupError                    # 由索引和key值引起的异常

        - IndexError                 # 索引错误

        - KeyError                   # 字典key值错误

    - MemoryError                    # 内存溢出异常

    - NameError                      # 本地和全局找不到变量名

        - UnboundLocalError          # 局部变量没有赋值

    - OSError                        # system错误

        - BlockingIOError            # 调用阻塞异常错误

        - ChildProcessError          # 子进程

        - ConnectionError            # 连接

            - BrokenPipeError        # 管道读写异常

            - ConnectionAbortedError # 连接失败

            - ConnectionRefusedError # 连接拒绝

            - ConnectionResetError   # 连接重置

        - FileExistsError            # 创建文件和文件夹错误

        - FileNotFoundError          # 文件未找到

        - InterruptedError           # 中断错误

        - IsADirectoryError          # 文件操作用在文件夹上

        - NotADirectoryError         # 不是文件夹

        - PermissionError            # 权限

        - ProcessLookupError         # 进程不存在

        - TimeoutError               # 超时

    - ReferenceError                 # 引用异常

    - RuntimeError                   # 

        - NotImplementedError        # 运行抽象方法

        - RecursionError             # 超出最大递归深度

    - SyntaxError                    # 语法错误

        - IndentationError           # 缩进错误

            - TabError               # tab错误

    - SystemError                    # 解释器中断

    - TypeError                      # 类型错误

    - ValueError                     # 赋值错误

        - UnicodeError               # 

            - UnicodeEncodeError     # unicode编码错误

            - UnicodeDecodeError     # unicode解码错误

            - UnicodeTranslateError  # unicode转换错误

    - Warning                        # 

        - DeprecationWarning         # 操作不赞成警告

        - PendingDeprecationWarning  # 表明此操作将来会被弃用

        - UserWarning                # 用于用户生成警告

        - SyntaxWarning              # 语法可疑警告

        - RuntimeWarning             # 运行警告

        - FutureWarning              # 将会改变警告

        - ImportWarning              # 导入警告

        - UnicodeWarning             # unicode相关警告

        - BytesWarning               # 字节相关警告

        - ResourceWarning            # 资源使用情况警告

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值