微信扫一扫打赏支持

python疑难问题---7、python中的with...as...

python疑难问题---7、python中的with...as...

一、总结

一句话总结:

with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。
with open("test.txt") as file:
    data = file.read()
    print(data)
等价于
try:
    file = open("test.txt")
    data = file.read()
    print(data)
finally:
    file.close()

 

1、with...as...语句会捕获异常,会处理异常么?

with...as...语句只会捕获异常,但是不会处理异常
with open("test.txt") as file:
    data = file.read()
    print(data)

如果没有test.txt,还是会出现以下错误

FileNotFoundError                         Traceback (most recent call last)
<ipython-input-4-bf5e860f28d5> in <module>
      1 try:
----> 2     file = open("test.txt")
      3     data = file.read()
      4     print(data)
      5 # except Exception as err:

FileNotFoundError: [Errno 2] No such file or directory: 'test.txt'

 

 

 

二、python中的with...as...

博客对应课程的视频位置:7、python中的with...as...-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/320

 

一、With语句是干什么的?

有一些任务,可能事先需要设置,事后做清理工作。对于这种场景,Python的with语句提供了一种非常方便的处理方式。

一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取数据,然后关闭文件句柄。

如果不用with语句,代码如下:

In [1]:
file = open("test.txt")
data = file.read()
print(data)
file.close()
aaaaaaaaaa

这里有两个问题

  • 一是可能忘记关闭文件句柄;

  • 二是文件读取数据发生异常,没有进行任何处理。

下面是处理异常的加强版本:

In [4]:
try:
    file = open("test.txt")
    data = file.read()
    print(data)
# except Exception as err:
#     print("捕获到异常,异常信息为{}".format(err))
finally:
    file.close()
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
<ipython-input-4-bf5e860f28d5> in <module>
      1 try:
----> 2     file = open("test.txt")
      3     data = file.read()
      4     print(data)
      5 # except Exception as err:

FileNotFoundError: [Errno 2] No such file or directory: 'test.txt'
这种结构简单的说:无论异常是否发生,在程序结束前,finally中的语句都会被执行。

虽然这段代码运行良好,但是太冗长了。

这时候就是with一展身手的时候了。

除了有更优雅的语法,with还可以很好的捕获上下文环境产生的异常(但是并不能处理)。

下面是with版本的代码:

In [6]:
with open("test.txt") as file:
    data = file.read()
    print(data)
aaaaaaaaaa

等价于:

In [ ]:
try:
    file = open("test.txt")
    data = file.read()
    print(data)
finally:
    file.close()
with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源, 比如文件使用后自动关闭、线程中锁的自动获取和释放等。
 

二、with工作原理

with基本思想是with所求值的对象必须有一个enter()方法,一个exit()方法。

下面程序定义了一个 People 类,并包含了 enter() 和 exit() 两个方法,因此该类的对象可以被 with as 语句管理。

In [7]:
class People:
    def __enter__(self):
        print("In __enter__()")
        return "Fry"
 
    def __exit__(self, type, value, trace):
        print("In __exit__()")
 
def get_people():
    return People()
 
with get_people() as people:
    print("people:", people)
In __enter__()
people: Fry
In __exit__()

紧跟with后面的语句被求值后,返回对象的enter()方法被调用,这个方法的返回值将被赋值给as后面的变量。当with后面的代码块全部被执行完之后,将调用前面返回对象的exit()方法。

下面例子可以具体说明with如何工作:

正如你看到的,

  1. enter()方法被执行

  2. enter()方法返回的值 - 这个例子中是"Fry",赋值给变量'people'

  3. 执行代码块,打印变量"people"的值为 "Fry"

  4. exit()方法被调用

with另一个强大之处是它可以捕获异常。

可能你已经注意到People类的exit方法有三个参数- val, type 和 trace。 这些参数在异常处理中相当有用。

我们来改一下代码,看看具体如何工作的。

In [8]:
class Sample:
    def __enter__(self):
        return self
 
    def __exit__(self, type, value, trace):
        print("type:", type)
        print("value:", value)
        print("trace:", trace)
        # trace为None,代表没有异常
#         if trace is None:
#             print('没有异常时关闭资源')
#         else:
#             print('遇到异常时关闭资源')
 
    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 0x000001A1925AD6C8>
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-8-b2706e2d5815> in <module>
     18 
     19 with Sample() as sample:
---> 20     sample.do_something()

<ipython-input-8-b2706e2d5815> in do_something(self)
     14 
     15     def do_something(self):
---> 16         bar = 1/0
     17         return bar + 10
     18 

ZeroDivisionError: division by zero
In [ ]:
 
系列博客对应课程视频地址:
1、遍历列表的三种方式-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/293
2、字典排序-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/294
3、可变和不可变数据类型-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/295
4、python文件处理-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/305
5、二维列表初始化-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/306
6、python中浅拷贝和深度拷贝-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/307
7、python中的with...as...-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/320
8、只有一个数的元组表示-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/343
9、Python类中call函数的作用-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/361
10、python遍历字典的几种方式-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/368
11、python内嵌for...in循环-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/369
12、python生成器-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/370
13、Python切片操作-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/377
 
 
posted @ 2020-07-09 09:23  范仁义  阅读(247)  评论(0编辑  收藏  举报