Python上下文管理器with深入讲解

Python编程时用到with上下文管理器的地方很多,但大多数人只知道怎么用却没有深入了解它。在此我尝试对Python上下文管理器with进行深入讲解,希望能帮到大家更好和更深入地掌握with的用法。

with作用

with语句是上下文管理器,上下文管理器(是一个对象)定义了在进入和退出with语句时需要执行上下文代码块。完整的上下文管理器必须有以下两个方法:

object.__enter__(self)
进入with语句块时会自动运行该对象的__enter__方法,如果有as子句那么with语句将将此方法的返回值绑定到as指定的目标。

object.__exit__(self, exc_type, exc_value, traceback)
退出with语句块时会自动执行此对象的__exit__方法,三个参数分别描述了导致上下文退出的异常。 如果上下文是无异常地退出的那么这三个参数都将为None。如果希望遇到异常时不抛异常那么需要return True;否则会正常流程处理。

注意:Python解释器会保证执行with语句时只要__enter__方法未报错那么__exit__方法总是会被调用。

with应用场景

在很多具有打开和关闭动作的场景都可以用with语句,常见的应用场景有打开和关闭文件、线程池、进程池、socket等等。

以下是使用with和不使用with的代码对比:

  • 不使用with打开文件的代码:

    try:
        f = open('z.txt', mode='rt')
        print(f.read())
    except FileNotFoundError:
        print('文件不存在')
    finally:
        f.close()
    
  • 使用with语句打开文件的代码:

    with open('a.txt', mode='rt') as f:
        print(f.read())
    

通过对比我们可以发现使用with可以让代码简洁优雅!

with特殊用法

with语句可以嵌套使用,也可以单句复用。下面列举一个读写文件的案例。
读取a.txt文件的内容,将其追加到b.txt文件中:

  1. 嵌套使用with:

    with open('a.txt', mode='rt') as r:
        with open('b.txt', mode='a+') as w:
            result = '\n'+r.read()
            w.write(result)
    
  2. 单句使用with:

    with open('a.txt', mode='rt') as r, open('b.txt', mode='a+') as w:
        result = '\n'+r.read()
        w.write(result)
    

两种用法结果完全一致,我更推荐第二种用法,代码更加简洁优雅。

with自定义

下面写了一个自定义的OpenFile类,用来演示with自定义上下文管理器的方法。望能起到抛砖引玉的效果,让大家学会with上下文管理器的自定义方法。

  • with自定义OpenFile类打开文件:

    import io
    
    
    class OpenFile(io.TextIOWrapper):
        def __init__(self, name, mode='rt'):
            self.code = True
            try:
                self.f = open(name, mode)
            except IOError:
                self.code = False
    
        def __enter__(self):
            if self.code:
                return self.f
            else:
                return False
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            if self.code:
                self.f.close()
                return True
    
    
    with OpenFile('c.txt') as f:
        if f:
            print(f.read())
        else:
            print('文件打开错误')
    print('后续代码')
    

    说明:

    使用with自定义OpenFile类打开文件时,如果该文件存在则会将文件句柄赋值给as的目标;如果该文件不存在那么会将False赋值给as的目标。

    在with语句内部,我们可以通过判断f的值来执行正确的分支。

    使用with自定义OpenFile类打开文件时无论遇到何种情况代码都可以执行完毕不报错。

  • 系统默认with open方式打开文件代码:

    with open('c.txt') as f:
        if f:
            print(f.read())
        else:
            print('文件打开错误')
    print('后续代码')
    

    说明:

    使用系统默认的with open方式打开文件时,如果文件存在那么所有代码可以正常执行完毕。
    如果文件不存在在open时就会抛Traceback异常,后续的代码都不会执行。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值