浅谈python的上下文管理

上下文管理的作用:
1.操作(创建/获取/释放)资源;
2.处理异常;
上下文管理的好处:
1.提高代码的复用率;
2.提高代码的优雅度;
3.提高代码的可读性;

好,带着上下文管理器的好处和作用进入正题…
什么是上下文管理器: 上下文管理器是指在一段代码执行之前执行另一段代码,用于一些预处理工作;执行之后再执行另一段代码,用于一些清理工作。可以理解为一个助理、管家,你在做什么事情之前他们会帮你安排好一切和之后的善后。
在平时敲代码过程中我们经常用到下面这段代码:

with open('test.txt', 'rb') as f:
    print f.readlines()

没错上下文管理器的基础语法就是:

with ... as ...:
	处理代码块

1.上下文表达式:with open(‘test.txt’) as f:;
2.上下文管理器:open(‘test.txt’);
3. f 是上下文表达式返回的资源对象;

在实现上下文管理之前我们还要知道上下文管理器之间的协议:
简单来说就是在类里面实现了__enter__和__exit__的方法,enter负责获取、连接资源,然后返回给处理代码块进行处理,最后的释放资源、处理异常都交由exit方法处理。

class Resource():
    def __enter__(self):
        print("获取资源......")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("exc_type:%s" % exc_type)
        print("exc_val:%s" % exc_val)
        print("exc_tb:%s" % exc_tb)
        print('释放资源......')
        # return True


with Resource() as res:
    a = 1 / 0

结果:
在这里插入图片描述

这里提一下exit里面的return和携带的三个参数:
return:为True就相当于告诉 Python解释器,这个异常我们已经捕获了,不需要再往外抛了(这就是with打开文件失败也不会报错的原因),默认是False。
exc_type:异常类型
exc_val:异常值
exc_tb:异常的错误栈信息

理解上面的所有之后,来模拟实现下文件的操作就对上下文管理器的作用和好处一目了然了。
正常操作文件:

file = open("text.txt", "r")
try:
    file.read()
except Exception as exc:
    print(exc)
finally:
    file.close()
    
file = open("text.txt", "w")
try:
    file.write("aaa")
except Exception as exc:
    print(exc)
finally:
    file.close()

我们要去捕获异常处理异常最后都要关闭文件,这样是不是很麻烦。那接下来就手动实现下上下文管理器,并操作文件的读写功能:
类的实现:

class OPEN():
    def __init__(self, path, mode="r"):
        self.path = path
        self.mode = mode

    def __enter__(self):
        self.file = open(self.path, mode=self.mode)
        return self.file

    def read(self):
        self.file.read()

    def write(self, content):
        self.file.write(content)

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.file.close()
        return True


file = open("./text.txt")
print(file)
with OPEN("./text.txt", "r") as f:
    print(f)
    f.read()
with OPEN("./text.txt", "w") as f:
    print(f)
    f.write("123")

如果只是要实现一个简单的功能,写一个类未免有点过于繁杂,如果能用一个函数就能解决掉干嘛非要一个类呢?
函数实现:

import contextlib


@contextlib.contextmanager
def OPEN(path, mode):
    # __enter__方法
    file_handler = open(path, mode)
    try:
        yield file_handler
    except Exception as exc:
        print(exc)
    finally:
        # __exit__方法
        file_handler.close()
        return


with OPEN('text.txt', 'w') as f:
    f.write("hhh")
with OPEN('text.txt', 'r') as f:
    print(f.read())

只要给函数加上contextlib.contextmanager装饰器就可以变成一个上下文管理器,就可以使用with调用了。

总结: 可以看出来主代码处只负责对返回的数据进行处理,而所有的文件打开、关闭操作和异常的处理都交由OPEN函数或类去实现,这样我们操作文件的时候就不用每次去打开、关闭文件,遇到异常还要进行捕获处理。所以才会用管家、助手来比喻最合适不过了,我只要告诉管家我要什么文件,管家就会帮我们找到文件打开等待处理,如果发现文件内容不对是不是管家开始到处查看哪里出了问题,并关闭文件收走。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python中,上下文管理器是一种处理资源的方式,它能够自动分配并且释放资源,比如打开和关闭文件、数据库连接等。上下文管理器通常使用with语句来实现,保证了代码块执行完毕后,资源被释放。Python提供了两种实现上下文管理器的方式:使用类和使用装饰器。 使用类实现上下文管理器时,需要定义一个类,并且实现`__enter__()`和`__exit__()`方法。`__enter__()`方法会在进入代码块前被调用,它负责资源的分配;`__exit__()`方法则会在代码块执行完成后被调用,负责资源的释放。 以下是一个简单的示例: ```python class MyContext: def __init__(self, resource): self.resource = resource def __enter__(self): print("Entering context...") return self.resource def __exit__(self, exc_type, exc_val, exc_tb): print("Exiting context...") self.resource.close() with MyContext(open("file.txt", "w")) as f: f.write("Hello World!") ``` 使用装饰器实现上下文管理器时,需要定义一个函数,并且使用`@contextlib.contextmanager`装饰器修饰它。这个函数需要使用`yield`语句将控制权传递给with语句块,然后在finally块中释放资源。 以下是一个简单的示例: ```python from contextlib import contextmanager @contextmanager def my_context(resource): try: print("Entering context...") yield resource finally: print("Exiting context...") resource.close() with my_context(open("file.txt", "w")) as f: f.write("Hello World!") ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值