又是学习进步的一天😊,今天我们来学习Python🐍中的上下文管理器,英文名字Context Managers
上下文管理器是一种用于管理资源的机制,它确保在使用资源后,无论使用过程中是否出现异常,都能够正确地释放或清理资源。Python中的上下文管理器主要通过 with 语句来实现,它可以提供更优雅、更安全的资源管理方式。
上下文管理器通常用于打开文件、数据库连接、网络连接、锁等需要手动管理的资源,以确保资源在使用完毕后能够正确地关闭或释放。
上下文管理器的基本结构
class MyContext:
def __enter__(self):
# 在进入上下文时执行的操作
return resource # 返回资源对象
def __exit__(self, exc_type, exc_value, traceback):
# 在退出上下文时执行的操作,无论是否发生异常
# exc_type: 异常类型,exc_value: 异常值,traceback: 异常堆栈跟踪
# 返回 True 表示异常被处理,不再传播;返回 False 或 None 表示异常继续传播
__enter__ 和 __exit__ 是上下文管理器协议中的两个特殊方法,用于定义进入和退出上下文时的操作。当使用 with 语句管理资源时,这些方法会在进入和退出上下文时被自动调用,以确保资源的正确管理和释放。
__enter__ 方法:
__enter__ 方法在进入上下文时被调用,它通常用于执行初始化操作或获取资源。该方法可以返回一个值,这个值会被绑定到 as 关键字之后的变量,从而可以在 with 块中使用。如果没有返回值,则默认返回上下文管理器自身。
class MyContext:
def __enter__(self):
print("你好我是 __enter__")
return self # 返回自身,以便在 with 语句中使用
def __exit__(self, exc_type, exc_value, traceback):
print("你好我是 __exit__")
def hello(self):
print('你好我是 小哥哥')
with MyContext() as context:
context.hello()
输出结果为:
__exit__ 方法:
__exit__ 方法在退出上下文时被调用,它通常用于执行清理操作或释放资源。它接受3个参数:exc_type、exc_value、traceback。如果上下文是无异常地退出的,三个参数都将为 None。如果出现错误,按顺序返回异常类型、异常描述、异常对象。
在 __exit__ 方法中,您可以选择是否处理异常。如果您希望异常继续传播,只需在方法中不做任何处理即可。如果您希望处理异常并阻止其传播,可以在方法中返回 True。如果您希望异常继续传播,但也希望在处理完异常后执行一些清理操作,可以返回 False 或 None。
class MyContext:
def __enter__(self):
print("你好我是 __enter__")
def __exit__(self, exc_type, exc_value, traceback):
if exc_type is None:
print("你好我是 __exit__,目前很正常")
else:
print(f"你好我是 __exit__,发生了异常: 异常类型是:{exc_type}, 异常的值为:{exc_value}")
with MyContext():
print("大家好我是 context")
raise ValueError("这里主动抛出个ValueError")
输出结果为:
当异常时返回True就阻止了异常的传播,代码修改如下
def __exit__(self, exc_type, exc_value, traceback):
if exc_type is None:
print("你好我是 __exit__,目前很正常")
else:
print(f"你好我是 __exit__,发生了异常: 异常类型是:{exc_type}, 异常的值为:{exc_value}")
# 返回True阻止了异常的传播
return True
这里举1个简单的例子🌰
示例:文件操作的上下文管理器
class FileContext:
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
print('你好我是 __init__')
def __enter__(self):
self.file = open(self.filename, self.mode)
print('你好我是 __enter__')
return self.file
def __exit__(self, exc_type, exc_value, traceback):
self.file.close()
print('你好我是 __exit__')
with FileContext('example.txt', 'r') as file:
contents = file.read()
print(contents)
# 文件会在退出上下文时自动关闭
输出结果为:
上下文管理器其它方法介绍
除了上下文管理器的必需方法 __enter__ 和 __exit__,我们可以选择性地定义以下可选方法来实现特定的行为或功能:
1.__init__ 方法:虽然不是上下文管理器协议的一部分,但在上下文管理器的实现中,您可以使用 __init__ 方法来执行一些初始化操作。
2.__iter__ 方法:如果您的上下文管理器表示一个可迭代对象,您可以定义 __iter__ 方法,使得上下文管理器本身成为可迭代的。迭代器教程可以参考3分钟带你了解Python中的生成器和迭代器
3.__len__ 方法:如果您的上下文管理器表示一个集合,您可以定义 __len__ 方法,用于返回集合中元素的数量。
4.__getitem__ 和 __setitem__ 方法:如果您的上下文管理器表示一个可索引的对象,您可以定义这些方法以支持索引访问。
5.__call__ 方法:如果您希望您的上下文管理器可以像函数一样调用,您可以定义 __call__ 方法。
6.__str__ 和 __repr__ 方法:用于返回对象的字符串表示和可打印的表达形式。
7.其他自定义方法:您可以根据需要定义其他自定义方法,以满足特定的行为和需求。比如我们在上方示例中的hello() 方法
需要注意的是,上下文管理器的核心功能是通过 __enter__ 和 __exit__ 方法来实现的,其他方法主要是为了增强上下文管理器的功能或用法。在大多数情况下,只有 __enter__ 和 __exit__ 方法是必需的,其他方法是可选的,可以根据需要进行定义。
总结
学会使用上下文管理器,具有提高代码的可读性、可维护性,并降低资源管理错误的风险。 今天的教程你学会了吗?