我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈
入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈
虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈
PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)文章合集 👈👈
Oracle数据库教程:👉👉 Oracle数据库文章合集 👈👈
优 质 资 源 下 载 :👉👉 资源下载合集 👈👈
__enter__()
(进入)方法和__exit__()
(退出)方法__enter__()
(进入)方法中执行一些准备操作__exit__()
(退出)方法会接收到语句体执行时抛出的异常类型、异常的值和追踪信息# 自定义上下文管理器
class Test:
def __enter__(self):
print('enter方法')
return 'enter方法的返回值'
def __exit__(self, exc_type, exc_val, exc_tb):
"""
exc_type:异常类型
exc_val:异常的值
exc_tb:追踪信息对象Traceback
"""
print('exit方法', exc_type, exc_val, exc_tb)
# 使用自定义上下文管理器
with Test() as x:
print(x)
1 / 0
# ============输出结果============
# enter方法
# enter方法的返回值
# exit方法 <class 'ZeroDivisionError'> division by zero <traceback object at 0x000002009555F400>
# Traceback (most recent call last):
# File "E:\StudyCode\Python\14-异常处理\03-自定义上下文管理器.py", line 12, in <module>
# 1 / 0
# ZeroDivisionError: division by zero
# with 后面的 Test() 是创建一个类实例对象-上下文管理器
# 自动执行上下文管理器对象内部的 __enter__() 方法
# 比如文件操作的 open(),就可以把文件打开操作放到 __enter__() 方法内部
# 执行完 __enter__() 方法,会把这个方法的返回值赋值给 with 语句中 as 后面的变量 x
# 执行语句体: print(x) 和 1 / 0
# 最后自动执行上下文管理器对象内部的 __exit__() 方法,这个方法会接收到语句体抛出的异常(包含:异常类型、异常值和追踪信息对象)
# __exit__() 方法的返回值为 True 则不会再将接收到的异常往外抛出,如果返回值为 False 则将接收到的异常继续往外抛出
# 所有最后的清理操作都可以写到 __exit__() 方法中(比如文件操作中最后的关闭文件操作)
__exit__()
方法中接收到的追踪信息对象,我们也可以获取到对象的相关信息# 自定义上下文管理器
class Test:
def __enter__(self):
# print('enter方法')
return 'enter方法的返回值'
def __exit__(self, exc_type, exc_val, exc_tb):
"""
exc_type:异常类型
exc_val:异常的值
exc_tb:追踪信息对象
"""
# print('exit方法', exc_type, exc_val, exc_tb)
# 获取追踪信息对象的内容
import traceback
print(traceback.extract_tb(exc_tb))
return True
# 使用自定义上下文管理器
with Test() as x:
# print(x)
1 / 0
# ========== 输出结果 ==========
# [<FrameSummary file E:\StudyCode\Python\14-异常处理\03-自定义上下文管理器.py, line 22 in <module>>]
def Test():
print('Text函数', 1)
yield '返回值1'
print('Text函数', 2)
import contextlib
@contextlib.contextmanager
def Test():
print('Text函数', 1)
yield '返回值1'
print('Text函数', 2)
with Test() as x:
2 / 1
print(x)
# ========== 输出结果 ==========
# Text函数 1
# 返回值1
# Text函数 2
@contextlib.contextmanager
装饰之后yield
之前的语句就是上下文管理器中的__enter__
方法yield
语句就是执行 语句体yield
之后的语句就是上下文管理器中的__exit__
方法import contextlib
@contextlib.contextmanager
def Test():
try:
yield
except Exception as e:
print('异常:', e)
with Test() as x:
2 / 0
# ========== 输出结果 ==========
异常: division by zero
# 步骤解析
# try语句写在yield之前,会先执行
# 通过yield语句执行语句体 2/0,会抛出异常
# 执行yield后面的except语句捕获异常
close()
方法但不是上下文管理器的对象变成上下文管理器close()
方法,而且是要求最后必须执行close()
方法class Test:
def tt(self):
print('tt方法')
def close(self):
print('对象关闭,释放资源')
Test
类实例对象每次调用完tt()
方法后,都需要执行close()
方法关闭对象,释放资源Test
类当中增加__enter__()
和__exit__()
两个方法class Test:
def tt(self):
print('tt方法')
def close(self):
print('对象关闭,释放资源')
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.close()
# 要求:Test类实例对象每次调用完tt()方法后,都需要执行close()方法关闭对象,释放资源
with Test() as x:
x.tt()
# ========== 输出结果 ==========
# tt方法
# 对象关闭,释放资源
# 解析:为什么要在__enter__中返回一个self
# 因为我们需要在with语句里面去执行实例方法tt(),所以我们需要拿到这个实例对象
# 通过__enter__方法使用self将这个实例对象返回,就可以将这个实例对象赋值给with语句中的x
# 再通过 x 去调用实例方法 tt()
__enter__()
和__exit__()
两个方法,比较麻烦contextlib.closing()
函数来解决这个问题class Test:
def tt(self):
print('tt方法')
def close(self):
print('对象关闭,释放资源')
# 要求:Test类实例对象每次调用完tt()方法后,都需要执行close()方法关闭对象,释放资源
import contextlib
with contextlib.closing(Test()) as x:
x.tt()
contextlib.closing()
函数就能达到上面增加__enter__()
和__exit__()
两个方法的效果contextlib.nested()
函数在Python3.x中已经已弃用,仅做了解即可!with open('xx.jpg', mode='rb') as form_file:
with open('xx2.jpg',mode = 'wb') as to_file:
file_content = form_file.read()
to_file.write(file_content)
open()
对象的上下文管理器做嵌套contextlib.nested()
函数来处理import contextlib
with contextlib.nested(open('xx.jpg', mode='rb'), open('xx2.jpg', mode='wb')) as (form_file,to_file):
file_content = form_file.read()
to_file.write(file_content)
contextlib.nested
函数了with open('xx.jpg', mode='rb') as form_file, open('xx2.jpg', mode='wb') as to_file:
file_content = form_file.read()
to_file.write(file_content)