美文网首页
Python之上下文管理器

Python之上下文管理器

作者: 10xjzheng | 来源:发表于2019-10-11 16:50 被阅读0次

1.引入

我们时常会看到网上很多人写文件读写的代码的时候,常常是这么写的:

with open('test.txt', 'r') as f:
    print(f.read())
    # 其它操作

这个with有什么用呢?
我们来看看不用这种写法我们怎么写。
假如我们直接这么写:

f = open('test.txt', 'r') 
print(f.read())
# 其它操作
f.close()

这种写法有什么问题呢?
假如在做其它操作的时候,出错了,程序终止,f.close()不会执行,则f这个句柄会一直得不到释放,要是并发操作,这个就很严重了。
所以我们通常会这么写:

try:
    f = open('test.txt', 'r')
except Exception:
    pass
finally:
    f.close()

但是每个操作都要这么写,就很繁琐了。
with open('test.txt', 'r') as f的作用在于,如果发生异常,它会帮你执行f.close()。它的原理就是上下文管理器。

这里还有个需要注意的问题,假如你用write()来写入文件,操作系统通常是先写到内存,空闲的时候再写入磁盘。只有调用close()方法时,操作系统才保证把没有写入的数据全部写入磁盘。

再举个例子,假如你写了一个类,但是里面可能会抛出异常,如果异常你需要做一些收尾操作,比如关闭数据库,关闭文件句柄,关闭某些长连接。一个你可以try catch,两个你也忍,多少太多地方用到了你就晕了,复制黏贴复制黏贴,累。

于是上下文管理器应运而生。

2. 上下文管理器--with关键字

  • 基本语法:
with EXPR as VAR:
    BLOCK
  • 运行逻辑:
    1.执行EXPR的上下文管理器的 __enter__方法,as VAR可以省略,如果不省略,则将__enter__方法的返回值赋值给VAR
    2.执行代码块BLOCK
    3.调用上下文管理器中的的__exit__方法

  • 例子:

class FileHelper:
    def __init__(self, file_name):
        self.file_name = file_name
        self.file_handler = None

    def __enter__(self):
        print('-' * 10, 'enter', '-' * 10)
        self.file_handler = open(self.file_name, 'a+')
        return self.file_handler

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('-' * 10, 'exit', exc_type, exc_val, exc_tb)

with FileHelper('test.txt') as f:
    for line in f:
        print(line)
    raise IOError

执行结果:

---------- enter ----------
Traceback (most recent call last):
---------- exit <class 'OSError'>  <traceback object at 0x0000027AF786AF88>
  File "D:/PythonProjects/Test.py", line 30, in <module>
    raise IOError
OSError

可以看到,结果输出了enter和exit的打印输出。

3.异步上下文管理器--async with

旧的上下文管理器是这样实现的:

class Manager:
    async def __aenter__(self):
          

    async def __aexit__(self, exc_type, exc, tb):
        

新语法:

async with EXPR as VAR:
    BLOCK

例子:

async def do_task(domain, pageUrl):
    async with aiohttp.ClientSession() as session:
        async with session.request('GET', pageUrl) as resp:
            if resp.status != 200:
                raise Exception('http error, url:{} code:{}'.format(pageUrl, resp.status))
                html = await resp.read()  # 可直接获取bytes

这是我另一篇文章Golang协程与Python协程速度比较贴过来的代码,await 相当于 yield from

相关文章

  • Python之上下文管理器

    1.引入 我们时常会看到网上很多人写文件读写的代码的时候,常常是这么写的: 这个with有什么用呢?我们来看看不用...

  • 算法面试 - 问题记录

    python上下文管理器,装饰器? (1)上下文管理器知乎链接:https://zhuanlan.zhihu.co...

  • Python上下文管理器和with块

    python中with语句用起来很方便,那这后边的原理就是python中的上下文管理器。 1.什么是上下文管理器 ...

  • python 上下文管理器

    一、什么是上下文管理器? 上下文管理器类型是python的内置类型之一,上下文管理器的定义:允许用户自定义类来定义...

  • Python上下文管理器

    Context Manager 文档翻译 Python with语句支持上下文管理器定义的运行时上下文概念(run...

  • python上下文管理

    什么是上下文管理 上下文:context的直译, 指的是代码执行过程中的前后状态上下文管理器:python上下文管...

  • python 基础深入

    contextlib 上下文管理器 创建上下文管理实际就是创建一个类,添加enter和exit方法 Python...

  • Tornado源码分析(二)异步上下文管理(StackConte

    异步异常与上下文 在Python黑魔法---上下文管理器最后关于上下文的使用,提到了tornado的处理方式。本篇...

  • Python上下文管理器

    上下文管理器 概念:实现了上下文协议的对象即为上下文管理器。 上下文管理器的协议: __enter__进入的方法_...

  • Python:上下文管理器 与 contextlib 的用法解析

    1. 上下文管理器 1.1. 引言 在 python 语言中经常会使用 with ... as ... 语句,...

网友评论

      本文标题:Python之上下文管理器

      本文链接:https://www.haomeiwen.com/subject/wbqtmctx.html