实践是检验真理的唯一标准
"""
1、为什么使用with的时候,可以省去执行 对象.close()???
2、with到底做了什么???
with启动了对象的上下文管理器
3、上下文管理器协议:
__enter__: 进入
enter方法返回的结果被as后面的变量接收,with ... as f
__exit__: 退出
with中所有的语句执行完毕执行 执行 __exit__
该方法内会手动调用 self.close(),故省去执行 对象.close()
4、在python中所有实现了上下文管理器协议的对象 都可以用使用with操作
5、with中有报错 __exit__ 三个参数会抛出异常
"""
import requests
# 文件操作
f = open('斗罗大陆.txt', 'w')
f.close() # 关闭会话
# 创建会话
session = requests.Session()
session.close() # 关闭会话
# dir(n)返回参数的属性、方法列表
print(dir(f))
# ['_CHUNK_SIZE', '__class__', '__del__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_checkClosed', '_checkReadable', '_checkSeekable', '_checkWritable', '_finalizing', 'buffer', 'close', 'closed', 'detach', 'encoding', 'errors', 'fileno', 'flush', 'isatty', 'line_buffering', 'mode', 'name', 'newlines', 'read', 'readable', 'readline', 'readlines', 'reconfigure', 'seek', 'seekable', 'tell', 'truncate', 'writable', 'write', 'write_through', 'writelines']
print(dir(session))
# ['__attrs__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'adapters', 'auth', 'cert', 'close', 'cookies', 'delete', 'get', 'get_adapter', 'get_redirect_target', 'head', 'headers', 'hooks', 'max_redirects', 'merge_environment_settings', 'mount', 'options', 'params', 'patch', 'post', 'prepare_request', 'proxies', 'put', 'rebuild_auth', 'rebuild_method', 'rebuild_proxies', 'request', 'resolve_redirects', 'send', 'should_strip_auth', 'stream', 'trust_env', 'verify']
# 因 open() 和 Session()的属性都包含'__enter__', '__exit__'
# 所以可以用 with
with open('斗罗大陆.txt', 'w') as f:
f.write('唐三封神')
print('这里open()')
# 这里open()
with requests.Session() as session:
print('这里是Session()')
pass
# 这里是Session()
print('====自定义文件操作的上下文管理器协议 demo ==========================================')
# 对象里面既没有__enter__,也没有__exit__,用with报错
class MyOpenNo:
pass
# 对象里面 有__enter__,没__exit__,用with报错
class MyOpenNoExit:
def __enter__(self):
return self
# 对象里面__enter__、__exit__都有,用with正常
class MyOpen:
def __enter__(self):
print('这里是 __enter__')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('这里是 __exit__')
print('对象里面既没有__enter__,也没有__exit__,用with报错 ===================================')
with MyOpenNo() as f:
print('这里是with中的操作')
print('整个with执行已执行完')
# python3.9打印结果:
# AttributeError: __enter__
# Python3.11打印结果:
# TypeError: 'MyOpenNo' object does not support the context manager protocol
print('对象里面有__enter__,没__exit__,用with报错 ===================================')
with MyOpenNoExit() as f2:
print('这里是with中的操作')
print('整个with执行已执行完')
# python3.9打印结果:
# AttributeError: __exit__
# Python3.11打印结果:
# TypeError: 'MyOpenNoExit' object does not support the context manager protocol (missed __exit__ method)
print('对象里面__enter__、__exit__都有,用with正常 ===================================')
with MyOpen() as f3:
print('这里是with中的操作')
print('整个with执行已执行完')
# python3.9打印结果:
# 这里是 __enter__
# 这里是with中的操作
# 这里是 __exit__
# 整个with执行已执行完
# Python3.11打印结果:
# 这里是 __enter__
# 这里是with中的操作
# 这里是 __exit__
# 整个with执行已执行完
print('案例Demo自己写一个open类:===========================================')
class MyOpenDemo:
def __init__(self, filename, mode, encoding):
self.filename = filename
self.mode = mode
self.encoding = encoding
def __enter__(self):
print("---__enter__---方法")
self.f = open(self.filename, self.mode, encoding=self.encoding)
# print(这一行会报错__enter__)
return self.f
def __exit__(self, exc_type, exc_val, exc_tb):
"""
:param exc_type: 异常类型 例:NameError
:param exc_val: 异常信息 例:name '这一行会报错' is not defined
:param exc_tb: 异常溯源对象 例:溯源报错行 Traceback...File "D:\Documents\PycharmProjects\pythonCk_13\testCk_13.py", line 27, in <module>...
:return:
"""
print('----__exit__---')
self.f.close()
with MyOpenDemo('哔哩哔哩.txt', 'w', encoding='utf-8') as f:
print(f.write('东风快递,全球包邮,使命必达。'))
# print(这一行会报错)
# 打印结果:不添加报错代码“print(这一行会报错)”
"""
---__enter__---方法
15
----__exit__---
"""
# 打印结果:添加报错代码“print(这一行会报错)”
"""
---__enter__---方法
15
----__exit__---
Traceback (most recent call last):
File "D:\Documents\PycharmProjects\pythonCk_13\testCk_13.py", line 27, in <module>
print(这一行会报错)
NameError: name '这一行会报错' is not defined
"""
# 结论:
# 1、with内有报错代码时,__enter__、__exit__代码仍执行。
# 2、__exit__的三个参数会抛出with内的报错信息。
# 3、__enter__中有代码报错,with和__exit__内代码不执行。
f.write('检测__exit__中是否有关闭')
# 如果__exit__中没有close()打印结果:
# 不报错:文件正常执行
"""
---__enter__---方法
15
----__exit__---
"""
# 如果__exit__中有close()打印结果:
# 报错:提示文件已关闭
"""
ValueError: I/O operation on closed file.
"""
欢迎来到testingpai.com!
注册 关于