zoukankan      html  css  js  c++  java
  • with与“上下文管理器”——Python

    with与“上下文管理器”

    1. with语句的使用

    向文件中写入数据的示例代码:

    # 1、以写的方式打开文件
     f = open("1.txt", "w")
     # 2、写入文件内容
     f.write("hello world")
     # 3、关闭文件
     f.close()

    代码说明:

    • 文件使用完后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的

    这种写法可能出现一定的安全隐患,错误代码如下:

     # 1、以读的方式打开文件
     f = open("1.txt", "r")
     # 2、读取文件内容
     f.write("hello world")
     # 3、关闭文件
     f.close()

    运行:

    Traceback (most recent call last):
      File "/home/python/Desktop/test/xxf.py", line 4, in <module>
        f.write("hello world")
    io.UnsupportedOperation: not writable

    代码说明:

    • 由于文件读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用
    • 为了保证无论是否出错都能正确地关闭文件,我们可以使用try ... finally来解决

     安全写法, 代码如下:

    try:
        # 1、以读的方式打开文件
        f = open("1.txt", "r")
        # 2、读取文件内容
        f.write("xxxxx")
    
    except IOError as e:
        print("文件操作出错", e)
    
    finally:
        # 3、关闭文件
        f.close()

    运行结果:

    文件操作出错 not writable

    这种方法虽然代码运行良好,但是缺点就是代码过于冗长,并且需要添加try-except-finally语句,不是很方便,也容易忘记.

    在这种情况下,Python提供了 with 语句的这种写法,既简单又安全,并且 with 语句执行完成以后自动调用关闭文件操作,即使出现异常也会自动调用关闭文件操作。

    with 语句的示例代码:

    # 1、以写的方式打开文件
    with open("1.txt", "w") as f:
        # 2、读取文件内容
        f.write("hello world")
       

    2. 上下文管理器

    一个类只要实现了__enter__()和__exit__()这个两个方法,通过该类创建的对象我们就称之为上下文管理器

    上下文管理器可以使用 with 语句,with语句之所以这么强大,背后是由上下文管理器做支撑的,也就是说刚才使用 open 函数创建的文件对象就是就是一个上下文管理器对象。

    自定义上下文管理器类,模拟文件操作:

    定义一个File类,实现 __enter__() 和 __exit__()方法,然后使用 with 语句来完成操作文件, 示例代码:

    class File(object):
    
        # 初始化方法
        def __init__(self, file_name, file_model):
            # 定义变量保存文件名和打开模式
            self.file_name = file_name
            self.file_model = file_model
    
        # 上文方法
        def __enter__(self):
            print("进入上文方法")
            # 返回文件资源
            self.file = open(self.file_name,self.file_model)
            return self.file
    
        # 下文方法
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("进入下文方法")
            self.file.close()
    
    
    if __name__ == '__main__':
    
        # 使用with管理文件
        with File("1.txt", "r") as file:
            file_data = file.read()
            print(file_data)

    运行:

    进入上文方法
    hello world
    进入下文方法

    代码说明:

    • __enter__表示上文方法,需要返回一个操作文件对象
    • __exit__表示下文方法,with语句执行完成会自动执行,即使出现异常也会执行该方法。

    3. 上下文管理器的另外一种实现方式

    假如想要让一个函数成为上下文管理器,Python 还提供了一个 @contextmanager 的装饰器,更进一步简化了上下文管理器的实现方式。

    通过 yield 将函数分割成两部分,yield 上面的语句在 __enter__ 方法中执行,yield 下面的语句在 __exit__ 方法中执行,紧跟在 yield 后面的参数是函数的返回值。

    # 导入装饰器
    from contextlib import contextmanager
    
    
    # 装饰器装饰函数,让其称为一个上下文管理器对象
    @contextmanager
    def my_open(path, mode):
        try:
            # 打开文件
            file = open(file_name, file_mode)
            # yield之前的代码好比是上文方法
            yield file
        except Exception as e:
            print(e)
        finally:
            print("over")
            # yield下面的代码好比是下文方法
            file.close()
    
    # 使用with语句
    with my_open('out.txt', 'w') as f:
        f.write("hello , the simplest context manager")

    4. 小结

    • Python 提供了 with 语句用于简化资源释放的操作,使用 with 语句操作建立在上下文管理器(实现__enter__和__exit__)的基础上
    • Python 还提供了一个 @contextmanager 装饰器,更进一步简化上下管理器的实现,让一个函数可以成为上下文管理器,结合 with 语句来使用
  • 相关阅读:
    VMware虚拟机下实现NAT方式上网的小方法
    文件附件上传
    [转] 深入了解 HTML 5
    用JS获取图片尺寸
    Stream与byte的转换
    递归算法
    搞懂java中的synchronized关键字
    初学UML之用例图
    浅析tomcat nio 配置
    面向对象:单一任务原则(SRP)
  • 原文地址:https://www.cnblogs.com/zeon/p/13582541.html
Copyright © 2011-2022 走看看