如果需要精确的分配和释放资源,就需要上下文管理 context manager ,上下文管理器在 Python 中最常见的例子就是 with语句

有状态资源的管理

很多时候我们需要操作一些有状态的资源,例如 类文件、套接字等

通常情况下我们会 建立连接 —> 做一些事 —> 释放连接

如果没有 close ,只有程序中断或者服务端主动关闭才会释放资源,否则会一直占用资源,有兴趣的朋友可以试试下面的代码

在 macOS/Linux 上会抛出 OS Error 的异常,因为打开的 file descriptor 超过限制了,Windows 估计会蓝屏 😀

try..finally 清理资源

我们也可以通过 try..finally 语句来实现对资源的清理,无论是否触发异常,最后都将清理资源

with 语句

如果看过一些 Python 的教程或者书籍的朋友可能会了解,操作文件和套接字都建议使用 with 语句

with 语句下操作文件的代码非常的简洁,并且能够自动关闭文件,这是因为 TextIOWrapper 这个类实现了 __enter____exit__ 这两个魔术方法,也就是所谓的上下文管理

我们也可以自己实现一个 Open 类,使其实现上下文管理

__enter__ 方法是在 with 初始化时调用,__exit__ 方法在所有语句结束后调用,可以用来处理异常和关闭资源

异常处理

上下文管理器根据__exit__ 方法的返回值来决定是否抛出异常,如果没有返回值或者返回值为 False ,则异常由上下文管理器处理,如果为 True 则由用户自己处理

__exit__ 接受三个参数,exception_type、exception_value、traceback,我们可以根据这些值来决定是否处理异常

下面这个例子,捕捉了 AttributeError 的异常,并打印出警告

试着故意打错方法的名称,并没有引发异常

使用 contextmanager

由于上下文管理非常有用,Python 中有一个专门用于实现上下文管理的标准库,这就是 contextlib

有了 contextlib 创建上下文管理的最好方式就是使用 contextmanager 装饰器,通过 contextmanager 装饰一个生成器函数,yield 语句前面的部分被认为是 __enter__ 方法的代码,后面的部分被认为是 __exit__ 方法的代码

通过上面这种方法,我们就能够简单的创建一个支持上下文管理的函数

contextmanager 的简单实现

我之前实现过一个非常粗糙的 contextmanager 装饰器




HTTPX 基础教程-新乡seo|网站优化,网站建设_微信公众号:zeropython—昊天博客