python基础____学习笔记14 (with语句和上下文管理器)

一、with语句
为什么需要with 语句,
       1. 若你打开了一个文件,可使用完这个文件后却忘却了关闭,那么整个文件可能还在内存中,造成资源浪费;
       2. 若你以只读的方式打开一个文件,却往文件里面写点东西,这时候程序会奔溃,这时候文件又未正常关闭;

with 语句很好解决了上诉的烦恼, with语句 简单又安全,不管正常结束或者出现异常 都会自动关闭该文件

# 1、以追加的方式打开文件
with open("test.txt", "a") as f:
    # 2、读取文件内容
    f.write("hello world\n")
# 1、以读的方式打开文件,文件也会关闭
with open("test.txt", "r") as f:
    # 2、读取文件内容
    try:
        f.write("hello world\n")
    except:
        print('file not writable')

print('----end-----')

#file not writable
#----end-----

二、上下文管理器
为什么文件能使用with 语句,那是因为文件实现了__enter__()函数,__exit__()函数。
     方法__enter__:不接受任何参数,在进入with语句时被调用,其返回值被赋给关键字as后面的变量。
     方法__exit__:  接受三个参数, 异常类型、异常对象和异常跟踪。它在离开方法时被调用。如果__exit__返回False,将向上抛出所有的异常。

class FileManage(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

    # 下文方法
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("进入下文方法")
        print(f'exc_type:{exc_type}')
        print(f'exc_val:{exc_type}')
        print(f'exc_tb:{exc_tb}')
        self.file.close()
        print("文件已经关闭")
        return True

    def writesomething(self, text):
        self.file.write(text)


if __name__ == '__main__':
    # 使用with管理文件
    with FileManage("test.txt", "r") as f:
        f.writesomething('hello,world\n')
    print('----end-----')

输出:

进入上文方法
进入下文方法
exc_type:<class 'io.UnsupportedOperation'>
exc_val:<class 'io.UnsupportedOperation'>
exc_tb:<traceback object at 0x0000018EBC683648>
文件已经关闭
----end-----

以传入文件名和打开方式, 进入了__enter__  函数,打开文件 并返回 类本身实例, 但是却往里面写东西,此时出现出现异常,进入收尾工作__exit__, 打印出异常的类型。

如果__exit__ 返回值为False ,那么就会继续向上抛出异常,程序奔溃

进入上文方法
进入下文方法
exc_type:<class 'io.UnsupportedOperation'>
exc_val:<class 'io.UnsupportedOperation'>
exc_tb:<traceback object at 0x000002585C313688>
文件已经关闭
Traceback (most recent call last):
  File "F:/PythonPro/main.py", line 31, in <module>
    f.writesomething('hello,world\n')
  File "F:/PythonPro/main.py", line 25, in writesomething
    self.file.write(text)
io.UnsupportedOperation: not writable

三、上下文管理器装饰器 @contextmanager 实现
     一个函数若想成为上下文管理器,使用python提供的 @contextmanager 的装饰器,简化了上下文管理器的实现方式。
通过 yield 将函数分割成两部分:
      yield 上面的语句在 __enter__ 方法中执行;
      yield 下面的语句在 __exit__ 方法中执行;
     紧跟在 yield 后面的参数是函数的返回值。

# 导入装饰器
from contextlib import contextmanager


# 装饰器装饰函数,让其称为一个上下文管理器对象
@contextmanager
def myopenfile(file_name, file_mode):
    try:
        # 打开文件
        file = open(file_name, file_mode)
        # 1. yield之前的代码 是__enter__方法中执行的
        yield file # 3.yield 后面的参数是函数的返回值
        # 2. yield 下面的语句在 __exit__ 方法中执行
    except Exception as e:
        print(e)
    finally:
        print("-----end----")
        file.close()
# 使用with语句
with myopefile('out.txt', 'r') as f:
    f.write("hello , the simplest context manager")


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值