• python之with语句


    一、情景再现

      在Python中,我们在打开文件的时候,为了代码的健壮性,通常要考虑一些异常情况,比如:

    try:
        ccfile = open('/path/data')
        content = ccfile.readlines()
        ccfile.close()
    
    except IOError:
        log.write('no data read
    ')

      如果文件操作出现异常,则写一条错误日志;

      考虑一种情况,如果文件打开成功,但readlines()调用失败,异常处理会立即跳转到except处执行,这样文件关闭就没有机会被执行到了。

      一种解决办法就是将close()语句放到finally子句中去,finally的特点是不管有无异常,都会被执行到。

    try:
        try:
            ccfile = open('/path/data')
            content = ccfile.readlines()
    
        except IOError:
            log.write('no data read
    ')
    
    finally
        ccfile.close()

    try:
        try:
            ccfile = open('/path/data')
            content = ccfile.readlines()
    
        finally IOError:
            ccfile.close()
    
    except IOError:
        log.write('no data read
    ')

    但是上面的语句很不优雅。可以使用with语句:

    with open('/etc/passwd') as f:
        for line in f:
            print(line)

    二、with语句

      1、with语句仅仅能对支持上下文管理协议的对象使用。支持本协议的对象

    file
    decimal.Context
    thread.LockType
    threading.Lock
    threading.RLock
    threading.Condition
    threading.Semaphore
    threading.BoundedSemaphore

      2、with语句执行的解析:

      with context_expr() as var:

        doSomething()

    1. 当with语句执行时,便执行上下文表达式(context_expr)(一般为某个方法)来获得一个上下文管理器对象,上下文管理器的职责是提供一个上下文对象,用于在with语句块中处理细节:
    2. 一旦获得了上下文对象,就会调用它的__enter__()方法,将完成with语句块执行前的所有准备工作,如果with语句后面跟了as语句,则用__enter__()方法的返回值来赋值;
    3. 当with语句块结束时,无论是正常结束,还是由于异常,都会调用上下文对象的__exit__()方法,__exit__()方法有3个参数,如果with语句正常结束,三个参数全部都是 None;如果发生异常,三个参数的值分别等于调用sys.exc_info()函数返回的三个值:类型(异常类)、值(异常实例)和跟踪记录(traceback),相应的跟踪记录对象。
    4. 因为上下文管理器主要作用于共享资源,__enter__()和__exit__()方法基本是完成的是分配和释放资源的低层次工作,比如:数据库连接、锁分配、信号量加/减、状态管理、文件打开/关闭、异常处理等。

      3、自定义类使用with来管理

    class A(object):
        def __enter__(self):
            print('__enter__() called')
            return self
        
        def print_hello(self):
            print("hello world!")
    
        def __exit__(self, e_t, e_v, t_b):
            print('__exit__() called')
    
    # 首先会执行__enter__方法
    with A() as a:    # a为__enter__的返回对象
        a.print_hello()
        print('got instance')
    # 结束会执行__exit__方法

      输出结果:

    __enter__() called
    hello world!
    got instance
    __exit__() called

    三、contextlib模块实现上下文自动管理

    @contextmanager
    def context():
        print('entering the zone')
        try:
            yield
        except Exception as e:
            print('with an error %s'%e)
            raise e
        else:
          print('with no error')
    
    with context():
        print('----in context call------')

    输出:

    entering the zone
    ----in context call------
    with no error

     来源:http://www.cnblogs.com/chenny7/p/4213447.html

  • 相关阅读:
    spring 配置版本问题
    sublime与Emment
    工欲善其事必先利其器之浏览器篇
    工欲善其事必先利其器之windows篇
    工欲善其事必先利其器之搜索引擎
    营销自我
    java必备技能
    离线安装ADT和sdk
    eclipse的小技巧
    匿名内部类
  • 原文地址:https://www.cnblogs.com/skiler/p/6958344.html
Copyright © 2020-2023  润新知