全部学科
Python全栈
python
NodeJS全栈
nodejs
📝 1 篇文章 25 道配套习题

上下文管理器专题

专题说明

上下文管理器是Python资源管理的核心机制。本专题从with语句的底层原理出发,深入讲解__enter__和__exit__魔术方法、contextlib标准库工具、异常处理机制,以及自定义上下文管理器的设计与实现,帮助学习者掌握安全、优雅的资源管理模式。

学习目标

  1. 理解with语句的执行流程和底层原理
  2. 掌握__enter__和__exit__魔术方法的实现规范
  3. 熟练使用contextlib中的contextmanager和closing装饰器
  4. 掌握上下文管理器中的异常处理机制
  5. 能够设计和实现自定义上下文管理器

学习内容

本专题涵盖以下核心知识点:

with语句原理

  • with语句的底层执行流程
  • __enter__方法的调用时机和返回值
  • __exit__方法的调用时机和参数

魔术方法实现

  • __enter__方法:资源获取和初始化
  • __exit__方法:资源释放和异常处理
  • __exit__的参数:exc_type、exc_val、exc_tb
  • 返回值对异常传播的影响

contextlib工具

  • @contextmanager装饰器用法
  • contextlib.closing()的使用
  • contextlib.suppress()异常抑制
  • contextlib.redirect_stdout/stderr重定向

异常处理机制

  • __exit__中异常的处理和抑制
  • 异常传播与return True/False的关系
  • 嵌套with语句的异常传播链

实战应用

  • 文件操作的上下文管理
  • 数据库连接的事务管理
  • 锁和同步原语的上下文管理
  • 自定义上下文管理器的设计模式

学习建议

  1. 先理解with语句的基本用法,再深入底层原理
  2. 对比try-finally和with语句的代码差异
  3. 动手实现自定义上下文管理器,加深理解
  4. 注意区分contextmanager装饰器和类实现的适用场景

📝 配套习题(25 题)

💡 参考答案在文末
判断题
1

contextlib.contextmanager 装饰器可以将一个包含 yield 的普通函数转换为上下文管理器,yield 之前的代码等价于 __enter__ 方法,yield 之后的代码等价于 __exit__ 方法。

A

B

2

__exit__方法返回True可以抑制异常,使异常不再传播;返回False则异常会继续抛出。

A

B

3

A

B

4

自定义上下文管理器可以通过两种方式实现:定义__enter____exit__方法的类,或使用@contextmanager装饰器的生成器函数。

A

B

5

实现上下文管理器协议需要定义__enter____exit__两个方法,这是Python上下文管理器的核心协议。

A

B

6

Python支持嵌套使用with语句,可以同时管理多个资源,多个with语句可以写在同一行。

A

B

7

with语句用于简化资源管理,确保资源在使用后自动释放,即使发生异常也能正确清理。

A

B

单选题
8

以下哪种场景最适合使用自定义上下文管理器?

A

计算两个数的和

B

管理数据库事务(自动提交或回滚)

C

打印一行文本

D

判断一个数是否为偶数

9

with语句的执行流程是:

A

执行代码块 → 调用__enter__ → 调用__exit__

B

调用__enter__ → 执行代码块 → 调用__exit__

C

调用__exit__ → 执行代码块 → 调用__enter__

D

执行代码块 → 调用__exit__ → 调用__enter__

10

嵌套上下文管理器的退出顺序是:

A

先进入先退出(FIFO)

B

先进入后退出(LIFO)

C

随机顺序

D

按字母顺序

11

with语句块内发生异常时,以下哪项正确?

A

异常被忽略,继续执行

B

__exit__方法被调用后异常被重新抛出

C

__exit__方法不会被调用

D

程序直接终止,不调用任何方法

12

contextlib模块的suppress装饰器/函数的作用是:

A

输出异常信息

B

抑制指定的异常类型,不让异常传播

C

创建上下文管理器

D

重定向输出

13

__exit__(self, exc_type, exc_val, exc_tb)中的三个参数,当with块内没有异常时:

A

都是None

B

分别是异常类型、值、追踪信息

C

只有exc_type是None

D

参数为空

14

以下代码执行后会发生什么?

Python
class Handler:
    def __enter__(self):
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type:
            print(f'异常: {exc_type.__name__}')
            return exc_type == ValueError
        return False

with Handler():
    raise ValueError('test')
print('继续执行')
A

输出"异常: ValueError"和"继续执行"

B

输出"异常: ValueError",然后程序终止

C

ValueError异常被抛出

D

输出"继续执行"(无异常信息)

15

以下哪个是正确的自定义上下文管理器类实现?

A

python class MyContext: def start(self): return self def end(self): pass

B

python class MyContext: def __enter__(self): return self def __exit__(self): pass

C

python class MyContext: def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): return False

D

python class MyContext: def __init__(self): return self def __del__(self): pass

16

以下哪种情况__exit__方法不会被调用?

A

with块正常执行完毕

B

with块内发生异常

C

with块内使用return语句返回

D

程序在__enter__执行前崩溃

17

__enter__方法的返回值会赋给with语句中的哪个变量?

A

with语句中的对象实例

B

as关键字后的变量

C

__exit__方法的参数

D

不返回任何值

18

contextlib.ExitStack的主要用途是:

A

抑制异常

B

动态管理数量不定的多个上下文管理器

C

简化单个上下文管理器的创建

D

重定向输出

19

使用@contextmanager装饰器创建上下文管理器时,yield语句的作用是:

A

定义__exit__方法

B

返回值给as变量,分割__enter__和__exit__代码

C

终止上下文管理器

D

抑制异常

填空题
20

上下文管理器协议要求实现________________________两个方法。__enter__方法在进入with块时调用,其____________赋给as后的变量。__exit__方法在退出with块时调用,接收三个异常参数,返回True可以抑制异常。

21

多个with语句可以在同一行使用____________分隔,Python 3.10+支持用____________包裹。使用ExitStack可以动态管理____________的上下文管理器,通过enter_context方法添加新的上下文,退出时按后进先出顺序调用各__exit__。

22

__exit__方法接收三个异常参数:____________(异常类型)、____________(异常值)、____________(异常追踪)。无异常时三者都是None。返回True可抑制异常,返回False则异常继续抛出。

23

自定义上下文管理器有两种方式:方式一是定义类实现________________________方法,方式二是使用____________装饰器。类实现方式中,__exit__需要三个异常参数,返回True可抑制异常。生成器方式中,yield前的代码是enter逻辑,yield后的finally块是exit逻辑。

24

使用@contextmanager装饰器时,____________之前的代码相当于____________方法,____________的值赋给as后的变量,yield之后在finally块中的代码相当于__exit__方法。

25

with语句进入代码块前调用____________方法,退出代码块后调用____________方法。as关键字后的变量是____________方法的返回值。with语句确保资源在异常发生时也能正确释放。

参考答案
1.正确 2.正确 3.正确 4.正确 5.正确 6.正确 7.正确 8.B 9.B 10.B 11.B 12.B 13.A 14.A 15.C 16.D 17.B 18.B 19.B 20.__enter__;__exit__;返回值 21.逗号;括号;数量不定 22.exc_type;exc_val;exc_tb 23.__enter__;__exit__;@contextmanager 24.yield;__enter__;yield 25.__enter__;__exit__;__enter__
想在手机上练习这套专题?
使用微信卷王开发者小程序,打开首页顶部扫码功能识别二维码
← 上一个专题 Python内部机制专题
下一个专题 → 元编程专题
扫码体验小程序
加载中
想在手机上刷题学习?
使用微信卷王开发者小程序,打开首页顶部扫码功能识别二维码