美文网首页Python基础
Python:上下文管理器

Python:上下文管理器

作者: 子休_ | 来源:发表于2018-01-30 20:55 被阅读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 声明创建时,上下文管理器允许类做一些设置和清理工作。上下文管理器的行为由下面两个方法所定义:

    • __enter__(self)
      定义使用 with 声明创建的语句块最开始上下文管理器应该做些什么。注意 __enter__ 的返回值会赋给 with 声明的目标,也就是 as 之后的东西。

    • __exit__(self, exception_type, exception_value, traceback)
      当 with 声明语句块执行完毕(或终止)时,执行该函数。它可以用来处理异常,进行清理,或者做其他应该在语句块结束之后立刻执行的工作。如果语句块顺利执行, exception_type , exception_value 和 traceback 会是 None 。如果出现异常,则被该函数捕获,你可以选择处理这个异常或者重新抛出让用户来处理。


    一般来说,上下文管理器是这样定义的。这样我们可以直接用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端口还在被占用的情况。

    相关文章

      网友评论

      • c87c8b64251c:不愧是魔幻写法,没看懂。
        子休_:@卑诚 哈哈,待会我贴一个样例你就应该懂了。

      本文标题:Python:上下文管理器

      本文链接:https://www.haomeiwen.com/subject/weiczxtx.html