python with as的用法

with是对try…expect…finally语法的一种简化。

1 try except

python中try/except/else/finally语句的完整格式如下所示:

try:
     Normal execution block
except A:
     Exception A handle
except B:
     Exception B handle
except:
     Other exception handle
else:
     if no exception,get here
finally:
     print("finally")   

说明:

正常执行的程序在try下面的Normal execution block执行块中执行,在执行过程中如果发生了异常,则中断当前在Normal execution block中的执行跳转到对应的异常处理块中开始执行;

python从第一个except X处开始查找,如果找到了对应的exception类型则进入其提供的exception handle中进行处理,如果没有找到则直接进入except块处进行处理。except块是可选项,如果没有提供,该exception将会被提交给python进行默认处理,处理方式则是终止应用程序并打印提示信息;

如果在Normal execution block执行块中执行过程中没有发生任何异常,则在执行完Normal execution block后会进入else执行块中(如果存在的话)执行。

无论是否发生了异常,只要提供了finally语句,以上try/except/else/finally代码块执行的最后一步总是执行finally所对应的代码块。

2 with as

with后面跟的是一个对象,这个对象必须要有一个__enter__()方法,一个__exit__()方法。

代码执行时,首先对with后面的语句进行求值,得到一个对象,该对象的__enter__()方法会被调用,__enter__()方法的返回值会被赋给as 后面的变量。with as后面的语句块执行完毕或者抛出异常后,会调用前面返回对象的__exit__()方法。

使用python with as的用法中的两个例子

class Sample:
    def __enter__(self):
        print ("In __enter__()")
        return "Foo"
 
    def __exit__(self, type, value, trace):
        print ("In __exit__()")
 
def get_sample():
    return Sample()
 
with get_sample() as sample:
    print( "sample:", sample)

执行get_sample() 返回一个Sample对象;

执行该Sample对象的__enter__()方法;

输出In __enter__(),返回“Foo”赋值给sample;

执行print( "sample:", sample),输出sample: Foo;

执行该Sample对象的__exit__()方法,输出In __exit__()

结果如下

In __enter__()
sample: Foo
In __exit__()

__exit__方法有三个参数- val, type 和 trace,使用它们可以打印出异常信息。

class Sample:
    def __enter__(self):
        return self
 
    def __exit__(self, type, value, trace):
        print ("type:", type)
        print ( "value:", value)
        print ("trace:", trace)
 
    def do_something(self):
        bar = 1/0
        return bar + 10
 
with Sample() as sample:
    sample.do_something()

输出结果

type: <class 'ZeroDivisionError'>
value: division by zero
trace: <traceback object at 0x02D17AA8>
Traceback (most recent call last):
  File "D:/Study/code/python/exampleOfWith.py", line 30, in <module>
    sample.do_something()
  File "D:/Study/code/python/exampleOfWith.py", line 26, in do_something
    bar = 1/0
ZeroDivisionError: division by zero

在with后面的代码块抛出任何异常时,__exit__()方法被执行。正如例子所示,异常抛出时,与之关联的type,value和stack trace传给__exit__()方法,因此抛出的ZeroDivisionError异常被打印出来了。开发库时,清理资源,关闭文件等等操作,都可以放在__exit__方法当中。


 3 使用with as进行文件处理

在文件处理中,获取一个文件句柄,从文件中读取数据,然后关闭文件句柄。执行的语句如下

fileIn = open("D:/xiaoaojianghu_jinyong.txt",encoding='utf-8')
data = fileIn.read()
fileIn.close()

使用第一节的try语句进行异常处理

fileIn = open("D:/xiaoaojianghu_jinyong.txt",encoding='utf-8')
try:
    data = fileIn.read()
finally:
    fileIn.close()

使用with as,更加方便。

with open("D:/xiaoaojianghu_jinyong.txt",encoding='utf-8') as fileIn:
    data = fileIn.read()

查看open的定义(在_pyio.py)

    @property
    def closed(self):
        """closed: bool.  True iff the file has been closed.

        For backwards compatibility, this is a property, not a predicate.
        """
        return self.__closed

    def _checkClosed(self, msg=None):
        """Internal: raise a ValueError if file is closed
        """
        if self.closed:
            raise ValueError("I/O operation on closed file."
                             if msg is None else msg)

    ### Context manager ###

    def __enter__(self):  # That's a forward reference
        """Context management protocol.  Returns self (an instance of IOBase)."""
        self._checkClosed()
        return self

    def __exit__(self, *args):
        """Context management protocol.  Calls close()"""
        self.close()

 __enter__()会检查file是否是close

__exit__会调用close()。在文件处理完毕后或出现异常时,文件也可以被正常关闭。

参考 

python中的try/except/else/finally语句

python with as的用法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值