Python基础

Python:上下文管理器

2018-01-30  本文已影响49人  子休_

使用Python打开文件可以这样写:

try:
    file = open("error.log", "w")
    # some sentences
except Exception:
    pass
finally:
    file.close()

这样在打开文件,进行一些处理的时候,就算抛出了异常,也能正常的关闭文件。
但我们可以用更简洁的方法来完成这一步骤:

with open("error.log", "w") as file:
    # some sentences

这两个代码块实现的功能是等价的,但显然下面的更加简洁。这就是 上下文管理器

当对象使用 with 声明创建时,上下文管理器允许类做一些设置和清理工作。上下文管理器的行为由下面两个方法所定义:


一般来说,上下文管理器是这样定义的。这样我们可以直接用with语句打开Example的一个实例。

class Example:
    def __init__(self):
        pass

    def __enter__(self):
        return something

    def __exit__(self, exception_type, exception_value, traceback):
        something.close()

但有个魔幻的写法,如下:

class Closer:
    """一个上下文管理器,可以在with语句中使用close()自动关闭对象"""

    def __init__(self, obj):
        self.obj = obj

    def __enter__(self):
        return self.obj # 绑定到目标

    def __exit__(self, exception_type, exception_value, traceback):
        try:
            self.obj.close()
        except AttributeError: # obj没有close()方法
            pass

这可以包裹一些有close()方法但没有定义上下文管理的的object,来让这些object可以用with打开。

import socket

with Closer(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as server:
    server.bind(("0.0.0.0", 8000))
    server.listen(120)
    sock, address = server.accept()

socket这个模块本身是没有定义上下文管理器的,但它有一个close()方法需要在停止运行时调用。
而我们只需要一个Closer包裹住它,就可以在任何情况下,正确的关闭server。这样就不会出现明明这个程序停止运行了,8000端口还在被占用的情况。

上一篇下一篇

猜你喜欢

热点阅读