上下文管理器

[TOC]

第二章 上下文管理器

2.1 上下文管理器的定义

  • 上下文管理器是一个包装任意代码块的对象

  • 上下文管理器保证进入上下文管理器时, 每次代码执行的一致性

  • 当退出上下文管理器时, 相关的资源会被正确回收

  • 上下文管理器保证退出步骤的执行

2.1.1 与装饰器的异同

与装饰器类似, 它们都是包装其他代码的工具. 装饰器包装用于定义的代码块(函数/类), 上下文管理器可以包装任意格式的代码块.

2.1.2 用途

  • 作为确保资源被正确清理的一种方式

2.2 语法

2.2.1 with语句

使用with语句可以进入上下文管理器.

两段功能相同的代码

  • 前提: open()支持with语法

  • 实际上是with语句对其后代码进行求值(在代码段二中, 就是调用open函数). 该表达式会返回一个对象, 该对象包含两个特殊方法: __enter____exit__. __enter__方法返回的结果被复制给as关键字之后的变量

  • 使用上下文管理器重要原因是避免代码重复

2.2.2 __enter____exit__方法

__enter__方法

__enter__方法只接受self参数. 当对象返回时该方法立即执行.

__exit__方法

__exit__方法带有3个位置参数(不包括self):

  • 一个异常类型

  • 一个异常实例

  • 一个回溯

如果没有异常, 三个参数全被设置为None, 如果出现异常, 则参数被赋值.

简单示例

代码

输出

2.2.3 异常处理

  • 上下文管理器必须定义__exit__方法, 该方法可以选择性地处理包装代码块中出现的异常, 或者处理其他需要关闭- 上下文管理器状态的事情.

  • __exit__方法必须定义三个位置参数(不包括self参数)

  • 三种处理方法:

    • 传播异常: 让__exit__方法返回False

    • 终止异常: 让__exit__方法返回True

    • 抛出不同异常

2.3 编写上下文管理器的集中情形

2.3.1 资源清理

确保出现异常时正确关闭资源可以避免很多僵尸进程.

2.3.2 异常处理

传播异常

代码

输出

终止异常

代码

输出

注意

  • 没有返回表达式5 / 0的值, 异常在计算该值的过程中引发, 从而触发__exit__的运行.

处理特定异常

代码

输出

基于属性的异常处理

上下文管理器可以根据异常的类型决定是否处理异常, 也可以根据异常的属性来决定是否处理异常.

示例

输出

说明

  • 根据命令执行返回代码判断是否处理异常

最后更新于