zoukankan      html  css  js  c++  java
  • 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 [ ]:
     
     
  • 相关阅读:
    Linux守护进程的编程实现
    QUIC简单介绍
    oracle10G/11G官方下载地址集合 直接迅雷下载
    Linux 解决文件删除,但并没有改变磁盘可用性
    开始使用正则表达式
    Codeforces 442C Artem and Array(stack+贪婪)
    Drop dual
    ios结构体httpPost头结构
    一个人ACM(我们赶上了ACM)
    Linux svnserver存储路径和文件的详细解释
  • 原文地址:https://www.cnblogs.com/Renyi-Fan/p/13271573.html
Copyright © 2011-2022 走看看