前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >上下文管理器之《with操作文件为什么会自动关闭?》

上下文管理器之《with操作文件为什么会自动关闭?》

作者头像
清菡
发布2021-10-13 11:18:26
5100
发布2021-10-13 11:18:26
举报
文章被收录于专栏:清菡软件测试清菡软件测试

一、with操作文件为什么会自动关闭?

它的底层是通过上下文管理器实现的。

代码语言:javascript
复制
with open('test.txt','w',encoding='utf8')as f:
    f.write("国庆也别忘了学习啊")

# with后面跟的是一个上下文管理器对象
    

运行后自动生成:

通过with打开一个文件,默认编码是jdK形式写的,所以加上encoding指定编码为utf8。

f是文字操作的句柄,通过这个句柄就可以往里面写东西。或者已读模式打开,可以往里面读东西,读完之后,这个文件不用关闭。怎么实现的呢?

with关键字后面跟的是个对象,with关键字会触发后面这个对象open('test.txt','w',encoding='utf8')

不是with是上下文管理器,是with后面这个open('test.txt','w',encoding='utf8')对象是上下文管理器。

通过with处理后面这个上下文管理器的时候,它会触发上下文管理器里面的某个方法。

二、什么是上下文管理器?上下文管理器又是怎么实现的呢?

上下文管理器是一个Python对象,为操作提供了额外的上下文信息。这种额外的信息,在使用with语句初始化上下文,以及完成with块中的所有代码时,采用可调用的形式。

实现上下文管理器的话,只需要自己定义个类去实现。只需要在类里面实现2个方法,一个叫做enter方法,一个叫做exit方法。

1.enter方法是干嘛的?

当我们使用with去处理一个上下文管理器对象的时候,首先会调用这个对象里面的enter方法,然后将enter方法返回的内容返回到as f

这个f就相当于上下文管理器里面enter方法返回的一个对象(返回的一条数据)。它返回什么,f就是什么。

2.exit方法是干嘛的?

打开一个上下文管理器,当with里面的代码执行完了以后,那么就会触发上下文管理器里面的另外一个exit方法退出。

这个方法默认有4个参数:

object.__exit__(self,exc_type,exc_val,exc_tb)

exc_type:#异常类型

exc_val:#异常值

exc_tb:#异常回溯追踪

它会把异常数据存储起来,在这个上下文管理器内部发生异常的时候,它能够自动将你异常的信息捕获到,传递到这个方法里面来。

open是python内置实现的一个上下文管理器。

三、自己手写一个操作文件的上下文管理器

上下文管理器就是个对象,先定义个类,继承object。实现一个enter方法,这个方法返回的内容就是f。

要实现上下文管理器必须两个方法,还有个方法是exit。这个方法默认有4个参数,不要去动它。

操作文件的时候,这里有3个参数open('test.txt','w',encoding='utf8'),其中encoding是个默认参数,可传可不传。

前面2个参数要传进来,open是个上下文管理器,其实也是个类。我们要操作文件,也得传文件名称和参数。

with MyOpen("text.txt","r")这里参数会传到哪里去?

通过类创建对象的时候,参数会传到init方法里面去。

实现一个init方法,不然传进去的参数接收不了。

定义一个init方法来接收。file_name是文件名,打开的一个方法是open_method。

这个时候传进来的

代码语言:javascript
复制

with MyOpen("text.txt","r")as f:
    pass

"text.txt","r"这两个参数就有地方接收了。

接收完毕后就要打开文件,打开文件返回f,f是哪个地方返回出来的?

return "python"这个地方返回出来的。

打印一下,看下f是个什么?

代码语言:javascript
复制
# with open('test.txt','w',encoding='utf8')as f:
#     f.write("国庆也别忘了学习啊")

# with后面跟的是一个上下文管理器对象

class  MyOpen(object):
    # 文件操作的上下文管理器类
    def __init__(self,file_name,open_method):
        self.file_name=file_name
        #做个初始化
        self.open_method=open_method
    def __enter__(self):
        return "python"
    def __exit__(self, exc_type, exc_val, exc_tb):
        pass

with MyOpen("test.txt","r")as f:
    pass
    print(f)

结果是:

with操作文件的时候其实就是对普通打开文件的一个封装。

上面第一个open的上下文管理器返回的是可操作文件的句柄,我也想返回一个可操作文件的句柄,可以这样修改代码:

代码语言:javascript
复制
# with open('test.txt','w',encoding='utf8')as f:
#     f.write("国庆也别忘了学习啊")

# with后面跟的是一个上下文管理器对象

class  MyOpen(object):
        # 文件操作的上下文管理器类
    def __init__(self,file_name,open_method):
        self.file_name=file_name#做个初始化
        self.open_method=open_method

    def __enter__(self):
        self.f=open(self.file_name,self.open_method) #普通打开文件的方式
        return self.f#如果不写self,要关闭文件,下面exit方法够不到

    def __exit__(self, exc_type, exc_val, exc_tb):
        pass

with MyOpen('test.txt','r') as f:
    print(f)

重点是这段代码:

代码语言:javascript
复制
self.f=open(self.file_name,self.open_method) #普通打开文件的方式
return self.f#如果不写self,要关闭文件,下面exit方法够不到

运行结果中有个cp936,windows中cp936代表文件打开方式是gbk。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-10-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 清菡软件测试 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、with操作文件为什么会自动关闭?
  • 二、什么是上下文管理器?上下文管理器又是怎么实现的呢?
    • 1.enter方法是干嘛的?
      • 2.exit方法是干嘛的?
      • 三、自己手写一个操作文件的上下文管理器
      相关产品与服务
      数据保险箱
      数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档