理解with,上下问管理器

简单理解with,上下问管理器

背景

对于系统资源如文件,数据库,socket而言,应用程序打开这些资源完成业务逻辑之后,必须关闭资源,不然资源会浪费占用空间,极端时系统会报错例如‘too many open files’

打开文件代码例子

def w1():
    f = open('1.txt', 'w')
    f.write('python')
    f.close()

这样写有个问题,如果在调用write的过程中,出现异常导致close无法正常被调用,该文件描述符资源就不会被释放。

进阶版

def w2():
    f = open('1.txt', 'w')
    try:
        f.write('python')
    except IOError:
        print('error')
    finally:
        f.close()

程序无论发生异常否,都肯定会执行到finally,文件每次都被被关闭。

推荐写法(with)

with open('1.txt', 'w') as f:
    f.write('python')

一种简单优雅的关键字with。open方法的返回值赋值给变量f,当离开with代码块的时候,系统会自动调用f.close()方法,with的作用和使用try/finally 语句是一样的。 那么with的原理是什么?那就不得不说python中的一个概念,就是上下文管理器(Context Manager)

上下文管理器

任何实现__enter__()和__exit__()方法的对象都可以称之为上下文管理器,上下文管理器对象可以使用with关键字

class File():
    def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode

    def __enter__(self):
        self.f = open(self.filename,self.mode)
        return self.f

    def __exit__(self, *args):
        self.f.close()

enter()方法返回资源对象,这里就是你打开的那个文件,exit()方法处理一些清除工作

with File('1.txt', 'w') as f:
    f.write('python')

使用with时调用File时,发现包含__enter__和__exit__方法,就会先调用__enter__,执行完或者出现异常时调用__exit__。

总结

当我们打开文件时,最好使用with open,根据需求也可以自己封装(包含__enter__和__exit__方法)如:

class open_excel(object):
    def __init__(self, path):
        self.path = path
        self.wb = None
        
    def __enter__(self):
        self.wb = openpyxl.load_workbook(self.path)
        return self.wb
    
    def __exit__(self, exc_type, exc_value, exc_tb):
        if self.wb:
            self.wb.save(self.path)
            self.wb.close()

python3中提供一个contextmanager的装饰器,更近一步简化了上下文管理器。通过yield将函数分割,yield之前的语句在__enter__方法中执行,yield之后的语句在__exit__方法中执行。yield 函数返回值。

from contextlib import contextmanager

@contextmanager
def my_open(path, mode):
    f = open(path, mode)
    yield f
    f.close()


with my_open('1.txt', 'w') as f:
    f.write('python')
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值