python中with的具体用法

作者:youhebuke225 时间:2021-12-08 17:41:16 

简介

with的基本表达式如下

with context_expression [as target(s)]:
   ...
   with-body

其中context_expression 可以是任意的表达式,as target(s)是可选的

他的执行过程如下

context_manager = context_expression
exit = type(context_manager).__exit__
value = type(context_manager).__enter__(context_manager)
exc = True   # True 表示正常执行,即便有异常也忽略;False 表示重新抛出异常,需要对异常进行处理
try:
   try:
       target = value  # 如果使用了 as 子句
       with-body     # 执行 with-body
   except:
       # 执行过程中有异常发生
       exc = False
       # 如果 __exit__ 返回 True,则异常被忽略;如果返回 False,则重新抛出异常
       # 由外层代码对异常进行处理
       if not exit(context_manager, *sys.exc_info()):
           raise
finally:
   # 正常退出,或者通过 statement-body 中的 break/continue/return 语句退出
   # 或者忽略异常退出
   if exc:
       exit(context_manager, None, None, None)
   # 缺省返回 None,None 在布尔上下文中看做是 False

深入

首先我们来了解两个概念,上下文管理对象与上下文协议

  • 上下文管理器:支持上下文管理协议的对象,这里我们就要知道什么是上下文管理管理协议了,请看第二点。上下文管理器运行with语句是要建立运行的上下文,负责执行with语句块上下文中的进入与退出操作。

  • 上下文管理协议:包含方法__enter__()和__exit__(),支持协议的对象要实现这两个方法

理解完上面的两点,我们就很容易知道with语句的执行流程,我们看着上面的执行过程代码来看

  • 执行context_expression ,生成山下文管理器context_manager

  • 调用上下文管理器的__enter__方法,这个时候如果使用了as,那么就会将__enter__方法的返回值赋值给target

  • 执行with-body

  • 不管执行过程中是否发生了异常都会执行上下文管理器的__exit__方法,它用于负责执行清理工作,如释放资源等。

  • 如果执行过程中没有出现异常,或者语句中执行了语句break/continue/return,则以None作为参数调用__exit__(None,None,None);如果执行过程中出现了异常,则使用sys.excinfo得到异常信息作为参数调用__exit__(exc_type,exc_value,exc_traceback)

  • 出现异常时,如果__exit__(exc_type,exc_value,exc_traceback)返回false,则会重新抛出异常,让with完的语句来处理异常,如果__exit__(exc_type,exc_value,exc_traceback)返回True,则异常忽略,不在对于异常来进行处理

代码

没有报错

class Test:
    def __enter__(self):
        print("__enter__")
        return "hello python"

    def __exit__(self, type, value, trace):
        print("__exit__")
        pass

def get_test():
    return Test()

with get_test() as test:
    print(test)

他的打印如下

__enter__
hello python
__exit__

有报错

class Test:
    def __enter__(self):
        print("__enter__")
        return "hello python"

    def __exit__(self, type, value, trace):
        print("type", type)
        print("value", value)
        print("trace", trace)
        print("__exit__")

def get_test():
    return Test()

with get_test() as test:
    print(test)
    1 / 0

 打印如下

hello python
type <class 'ZeroDivisionError'>
value division by zero
trace <traceback object at 0x0000024938B07B40>
__exit__
Traceback (most recent call last):
  File "f:/my_profile/study/code_pub/study_code_pub/python/关键字/with.py", line 35, in <module>
    1 / 0

可以看出来当有报错的时候,他是抛出了异常,因为__exit__没有返回值,当他返回True的时候,他的打印如下

当__exit__返回True时

__enter__
hello python
type <class 'ZeroDivisionError'>
value division by zero
trace <traceback object at 0x000001FB117885C0>
__exit__

我们会发现他没有了报错信息

来源:https://blog.csdn.net/youhebuke225/article/details/129098821

标签:python,with
0
投稿

猜你喜欢

  • Windows下Python使用Pandas模块操作Excel文件的教程

    2021-01-05 23:07:40
  • SQL语句参考及记录集对象详解

    2008-11-25 11:47:00
  • 微信公众号可通过现金红包接口发放微信支付现金红包(附开发教程)

    2023-06-28 10:24:42
  • Python使用pygame模块编写俄罗斯方块游戏的代码实例

    2021-11-15 02:29:29
  • vue2.0开发实践总结之疑难篇

    2024-05-02 16:33:28
  • 在Linux下搭建Git服务器的方法详解

    2022-02-05 16:35:10
  • Python离线安装包教程分享

    2023-08-03 18:16:40
  • web版Photoshop来了

    2008-04-21 13:39:00
  • Python中基本的日期时间处理的学习教程

    2023-08-25 08:16:19
  • Go Plugins插件的实现方式

    2023-10-15 01:51:20
  • Python中aiohttp的简单使用

    2022-05-29 05:43:33
  • Python linecache.getline()读取文件中特定一行的脚本

    2023-03-09 13:18:05
  • VS Code有哪些奇技淫巧(必知)

    2022-01-07 21:10:47
  • 在Python中将函数作为另一个函数的参数传入并调用的方法

    2023-04-10 07:32:26
  • python版本的读写锁操作方法

    2023-04-29 05:18:57
  • 高效的mysql分页方法及原理

    2024-01-20 04:23:46
  • python3使用pyqt5制作一个超简单浏览器的实例

    2023-04-12 19:44:51
  • Python实现生成对角矩阵和对角块矩阵

    2021-03-16 11:45:00
  • Python的Asyncore异步Socket模块及实现端口转发的例子

    2023-04-23 13:24:38
  • python如何将两张图片生成为全景图片

    2021-08-03 23:42:26
  • asp之家 网络编程 m.aspxhome.com