Python `with`语句的底层实现代码究竟是什么?
Python with语句的原生调用逻辑解析
你提到的with语句,本质是Python对上下文管理器协议的语法糖,底层对应以下几个明确的执行步骤:
执行步骤拆解
针对代码:
with with_target_expression() as with_variable: with_block_contents(with_variable)
获取上下文管理器对象
先执行with_target_expression(),得到一个上下文管理器对象——这个对象必须实现__enter__和__exit__两个特殊方法,这是上下文管理器协议的硬性要求。调用
__enter__方法并赋值变量
调用上述对象的__enter__()方法:- 如果有
as with_variable,就把__enter__方法的返回值赋值给with_variable(注意:不是把第一步得到的上下文管理器对象直接赋值,而是__enter__的返回值); - 如果没有
as语句,__enter__的返回值会被直接忽略。
- 如果有
执行代码块内容
运行with_block_contents(with_variable)这个代码块里的所有逻辑。调用
__exit__方法完成清理
不管代码块是正常执行完毕,还是中途抛出异常,一定会调用上下文管理器对象的__exit__(exc_type, exc_val, exc_tb)方法:- 三个参数分别对应异常类型、异常实例、回溯对象;如果代码块正常结束,这三个参数全为
None; - 如果
__exit__方法返回True,代码块中抛出的异常会被压制,程序继续执行后续代码;如果返回False(或无返回值,默认等价于False),异常会正常向上传播。
- 三个参数分别对应异常类型、异常实例、回溯对象;如果代码块正常结束,这三个参数全为
自定义上下文管理器示例
自己实现一个符合协议的类,就能直观看到底层调用过程:
class SimpleContext: def __enter__(self): print("[底层调用] 执行__enter__方法") return "传递给as的变量值" def __exit__(self, exc_type, exc_val, exc_tb): print(f"[底层调用] 执行__exit__方法,异常信息:{exc_type}, {exc_val}, {exc_tb}") # 返回True会压制异常,返回False则让异常继续抛出 return False # 测试执行流程 with SimpleContext() as var: print(f"代码块执行,var的值:{var}") # 可取消注释测试异常场景 # raise RuntimeError("测试异常抛出")
运行这段代码,控制台会按顺序输出调用过程,你能清晰看到__enter__、代码块、__exit__的执行顺序,以及异常发生时__exit__的参数变化。
内容的提问来源于stack exchange,提问作者Brondahl
相关产品推荐
相关产品推荐

