""" 模块:python3 with.py 参考: https://docs.python.org/zh-cn/3/reference/compound_stmts.html#with https://docs.python.org/zh-cn/3/reference/datamodel.html#context-managers https://blog.csdn.net/lxy210781/article/details/81176687 知识点: 0.with 语句用于包装带有使用上下文管理器 (参见 with 语句上下文管理器 一节) 定义的方法的代码块的执行。 with_stmt ::= "with" with_item ("," with_item)* ":" suite with_item ::= expression ["as" target] 带有一个“项目”的 with 语句的执行过程如下: 1.对上下文表达式 (在 with_item 中给出的表达式) 求值以获得一个上下文管理器。 2.载入上下文管理器的 __enter__() 以便后续使用。 3.载入上下文管理器的 __exit__() 以便后续使用。 4.发起调用上下文管理器的 __enter__() 方法。 5.如果 with 语句中包含一个目标,来自 __enter__() 的返回值将被赋值给它。 注解: with 语句会保证如果 __enter__() 方法返回时未发生错误,则 __exit__() 将总是被调用。 因此,如果在对目标列表赋值期间发生错误,则会将其视为在语句体内部发生的错误。 参见下面的第 6 步。 6.执行语句体。 7.发起调用上下文管理器的 __exit__() 方法。 如果语句体的退出是由异常导致的,则其类型、值和回溯信息将被作为参数传递给 __exit__()。 否则的话,将提供三个 None 参数。 如果语句体的退出是由异常导致的,并且来自 __exit__() 方法的返回值为假,则该异常会被重新引发。 如果返回值为真,则该异常会被抑制,并会继续执行 with 语句之后的语句。 如果语句体由于异常以外的任何原因退出,则来自 __exit__() 的返回值会被忽略, 并会在该类退出正常的发生位置继续执行。 实例: 1.with EXPRESSION as TARGET: SUITE 2.如果有多个项目,则会视作存在多个 with 语句嵌套来处理多个上下文管理器: with A() as a, B() as b: SUITE 在语义上等价于: with A() as a: with B() as b: SUITE 1.with 语句上下文管理器 上下文管理器 是一个对象,它定义了在执行 with 语句时要建立的运行时上下文。 上下文管理器处理进入和退出所需运行时上下文以执行代码块。 通常使用 with 语句(在 with 语句 中描述),但是也可以通过直接调用它们的方法来使用。 上下文管理器的典型用法包括保存和恢复各种全局状态,锁定和解锁资源,关闭打开的文件等等。 object.__enter__(self) 进入与此对象相关的运行时上下文。 with 语句将会绑定这个方法的返回值到 as 子句中指定的目标,如果有的话。 object.__exit__(self, exc_type, exc_value, traceback) 退出关联到此对象的运行时上下文。 各个参数描述了导致上下文退出的异常。 如果上下文是无异常地退出的,三个参数都将为 None。 如果提供了异常,并且希望方法屏蔽此异常(即避免其被传播),则应当返回真值。 否则的话,异常将在退出此方法时按正常流程处理。 请注意 __exit__() 方法不应该重新引发被传入的异常,这是调用者的责任。 """ # 1.f 绑定了一个上下文管理器。 # 此处会自动调用文件的 close()。 with open(r'./明白牌.txt', 'r', encoding="utf-8") as f: data = f.read() # print("data:", data) print(f.closed) f = open("cs.txt") print(f.closed) # True # False # # Process finished with exit code 0 # 2.无异常发生 class Test: def __enter__(self): print('__enter__() is called!') return self def dosomething(self): print('do some thing!') def __exit__(self, exc_type, exc_value, traceback): print(f'type:{exc_type}') print(f'value:{exc_value}') print(f'trace:{traceback}') print('__exit()__ is called!') print("\n2.") with Test() as sample: sample.dosomething() # __enter__() is called! # do some thing! # type:None # value:None # trace:None # __exit()__ is called! # 3.有异常发生时,会抛出异常的例子。 class Test: def __enter__(self): print('__enter__() is called!') return self def dosomething(self): # x = 1 / 0 print('do some thing!') def __exit__(self, exc_type, exc_value, traceback): print(f'type:{exc_type}') print(f'value:{exc_value}') print(f'trace:{traceback}') print('__exit()__ is called!') print("\n3.") with Test() as sample: sample.dosomething() # __enter__() is called! # type:<class 'ZeroDivisionError'> # value:division by zero # trace:<traceback object at 0x000001B2B622AA80> # __exit()__ is called! # Process finished with exit code 1 # 4.有异常发生时,不抛出异常的例子: class Test: def __enter__(self): print('__enter__() is called!') return self def dosomething(self): x = 1 / 0 print('do some thing!') def __exit__(self, exc_type, exc_value, traceback): print(f'type:{exc_type}') print(f'value:{exc_value}') print(f'trace:{traceback}') print('__exit()__ is called!') return True print("\n4.") with Test() as sample: sample.dosomething() # __enter__() is called! # type:<class 'ZeroDivisionError'> # value:division by zero # trace:<traceback object at 0x0000013DCDE4C040> # __exit()__ is called! # Process finished with exit code 0
python3 with.py
最新推荐文章于 2024-04-26 12:04:47 发布