Python中的with,没那么简单,虽然也不难

https://docs.python.org/zh-cn/3.9/reference/compound_stmts.html#the-with-statement 8.3 with 语句

https://docs.python.org/zh-cn/3.9/reference/datamodel.html#context-managers 3.3.9 with语句上下文管理器

with 语句

  • 语法

    with_stmt ::=  "with" with_item ("," with_item)* ":" suite
    with_item ::= expression ["as" target]
  • 执行过程

    1. 对上下文表达式 (在 with_item 中给出的表达式) 求值以获得一个上下文管理器。

    2. 载入上下文管理器的 __enter__() 以便后续使用。

    3. 载入上下文管理器的 __exit__() 以便后续使用。

    4. 发起调用上下文管理器的 __enter__() 方法。

    5. 如果 with 语句中包含一个目标,来自 __enter__() 的返回值将被赋值给它。

      with语句会保证如果 __enter__()方法返回时未发生错误,则 __exit__()将总是被调用。 因此,如果在对目标列表赋值期间发生错误,则会将其视为在语句体内部发生的错误。 参见下面的第 6 步。
    6. 执行语句体。

    7. 发起调用上下文管理器的 __exit__() 方法。 如果语句体的退出是由异常导致的,则其类型、值和回溯信息将被作为参

  • 说明

    • 如果语句体的退出是由异常导致的,并且来自 __exit__() 方法的返回值为假,则该异常会被重新引发。 如果返回值为真,则该异常会被抑制,并会继续执行 with 语句之后的语句。
    • 如果语句体由于异常以外的任何原因退出,则来自 __exit__() 的返回值会被忽略,并会在该类退出正常的发生位置继续执行

示例1:打开文件的with

  • 最常见的就是with打开文件

    with open(r'd:\with.txt','w') as f:
    f.write('hello')
    • 这样我们就不用去f.close()
    • 在这里你并不能从源码上看到enter和exit的影子
    • 底层是c代码的实现

    示例2:selenium中的with

    • SELENIUM中的WebDriver就是一个典型的实现了enter和exit的

    • 所以我们可以这么用(在selenium官网也有类似的DEMO)

      from selenium import webdriver
      from time import sleep with webdriver.Chrome() as driver:
      driver.get('https://www.baidu.com')
      sleep(2)
      • 上面的代码你运行后可以看到打开了一个chrome浏览器,输入了百度的网址,等待2s后自动关闭了
    • 我们来追溯下源码

      with webdriver.Chrome() as driver:   # ctrl+点击Chrome()
      
      class WebDriver(ChromiumDriver): # ctrl+点击ChromiumDriver
      
      class ChromiumDriver(RemoteWebDriver):  #  ctrl+点击RemoteWebDriver
      
      class WebDriver(BaseWebDriver):  #
      ... def __enter__(self):
      return self def __exit__(self,
      exc_type: typing.Optional[typing.Type[BaseException]],
      exc: typing.Optional[BaseException],
      traceback: typing.Optional[types.TracebackType]):
      self.quit()
      • 可以看到继承的WebDriver中实现了enter和exit,其实也没做啥,exit主要是退出了。
      • 这样你再来看下面的enter和exit的官方说明似乎更好理解一些

关于enter

  • object.__enter__(self)

    进入与此对象相关的运行时上下文。 with 语句将会绑定这个方法的返回值到 as 子句中指定的目标,如果有的话。

关于exit

  • object.__exit__(self, exc_type, exc_value, traceback)

    退出关联到此对象的运行时上下文。 各个参数描述了导致上下文退出的异常。 如果上下文是无异常地退出的,三个参数都将为 None。

    如果提供了异常,并且希望方法屏蔽此异常(即避免其被传播),则应当返回真值。 否则的话,异常将在退出此方法时按正常流程处理。

    请注意 __exit__() 方法不应该重新引发被传入的异常,这是调用者的责任

其他示例

  • 复制一个文件的内容到另外一个文件中,不考虑异常,只演示用法

    with open(r'd:\old.txt','r') as f1,open(r'd:\new.txt','w') as f2:
    f2.write(f1.read())
  • 打开多个网页,串行的。

    from selenium import webdriver
    from time import sleep
    with webdriver.Chrome() as driver1,webdriver.Chrome() as driver2:
    driver1.get('https://www.baidu.com')
    sleep(2)
    driver2.get('https://cn.bing.com')
    sleep(2)
  • with的另外一种写法:肯定是不建议的,但可以理解一下。

    with open(r'd:\old.txt','r') as f:   # 原始的写法,打印文件的内容
    print(f.read())
    import sys
    
    manager = open(r'd:\old.txt','r')
    enter = type(manager).__enter__
    exit = type(manager).__exit__
    value = enter(manager) hit_expect = False try:
    TARGET = value
    print(TARGET.read())
    except:
    hit_expect = True
    if not exit(manager,*sys.exc_info()):
    raise 'hehe'
    finally:
    if not hit_expect:
    exit(manager, None,None,None)
  1. 数传递给 __exit__()。 否则的话,将提供三个 None 参数

浅谈Python中的with,可能有你不知道的的更多相关文章

  1. 浅谈python中得import xxx,from xxx import xxx, from xxx import *

    在python中import跟from import都是用来导入的,但是导入的机制不同 1.import xxx:导入模块,或者文件夹,对于调用模块或者文件夹中子模块的变量或者函数,需要使用" ...

  2. 浅谈python中的“ ==” 与“ is”

    在python中,== 与 is 之间既有区别,又有联系,本文将通过实际代码的演示,力争能够帮助读到这篇文章的朋友以最短的时间理清二者的关系,并深刻理解它们在内存中的实现机制.扯淡的话不多说,下面马上 ...

  3. 浅谈python中文件和文件夹的相关操作

    文件操作 文件的打开与关闭 打开文件 使用open(文件名,访问方式)函数,可以打开一个已存在的文件,或者创建一个新的文件. 示例如下: f = open('test.txt') # 访问方式可以省略 ...

  4. 浅谈python中字典append 到list 后值的改变问题

    看一个例子 ? 1 2 3 4 d={'test':1} d_test=d d_test['test']=2 print d 如果你在命令行实践的话,会发现你改动的是d_test ,但是d 也跟着改变 ...

  5. 浅谈python中的闭包函数

    闭包函数初探 通常我们定义函数都是这样定义的 def foo(): pass 其实在函数式编程中,函数里面还可以嵌套函数,如下面这样 def foo(): print("hello worl ...

  6. 浅谈python中的“ ==” 与“ is”、还有cmp

    总之,比较内容相等使用 ‘==’ 1.is" 是用来比较 a 和 b 是不是指向同一个内存单元,而"=="是用来比较 a 和 b指向的内存单元中的值是不是相等 2.pyt ...

  7. 浅谈Python中函数式编程、面向对象编程以及古怪的PythonIC

    1.函数式编程作为结构化编程的一种,正在受到越来越多的重视.那么什么事函数式编程呢? 在维基百科中给出了详细的定义,函数式编程又称泛函数编程,是一种编程规范,它将函数运算视为数学上的函数计算.简单的来 ...

  8. 浅谈python中__str__和__repr__的区别

    很多时候我们在创建一个类的时候,在终端打印类或者查看的时候一般都不会得到一个太满意的结果 class T: def __init__(self): self.color="red" ...

  9. 浅谈Python 中 __getattr__与__getattribute__的区别

    __getattr__与__getattribute__均是一般实例属性截取函数(generic instance attribute interception method),其中,__getatt ...

  10. 浅谈python 中正则的一些函数

         主要的函数有  : match() search() findall() group() groups() split()  match (): 含义  开头匹配,匹配成功返回一个对象失败则 ...

随机推荐

  1. python 基本使用 异常判断

    简单常用 isinstance 判断一个对象是否是一个已知的类型 arg=123 isinstance(arg, int) #输出True isinstance(arg, str) #输出False ...

  2. AIR32F103(五) FreeRTOSv202112核心库的集成和示例代码

    目录 AIR32F103(一) 合宙AIR32F103CBT6开发板上手报告 AIR32F103(二) Linux环境和LibOpenCM3项目模板 AIR32F103(三) Linux环境基于标准外 ...

  3. Java开发学习(四十一)----MyBatisPlus标准数据层(增删查改分页)开发

    一.标准CRUD使用 对于标准的CRUD功能都有哪些以及MyBatisPlus都提供了哪些方法可以使用呢? 我们先来看张图: 1.1 环境准备 这里用的环境就是Java开发学习(四十)----MyBa ...

  4. 嵌入式-C语言基础:数组指针

    定义一个数组指针,指向二维数组: int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}}; int (*p)[4];//定义二维指针数组 p=a;//指向二维数组 ...

  5. K8Snode节点管理集群资源方法

    1.1 方法1 1.将master的admin.conf 文件拷贝到 node节点 [root@k8s-m ~]#scp /etc/kubernetes/admin.conf root@192.168 ...

  6. 基于python的数学建模---多模糊评价

    权重 ak的确定--频数统计法 选取正整数p的方法 画箱形图   取1/4与3/4的距离(IQR)  ceil()取整 代码: import numpy as np def frequency(mat ...

  7. typora使用CSDN图床

    前言 软件下载地址 typora 是一款好用的 markdown 文档编辑器. 我之前研究过CSDN上传图片的接口,前几天发现了Typora 这个好用的软件,可以自定义图床,因为我很多文章图片资源用的 ...

  8. MICCAI 论文投稿须知翻译

    MICCAI 论文投稿须知翻译 以MICCAI 2021 PAPER SUBMISSION AND REBUTTAL GUIDELINES为例,每年投稿须知类似 作者信息和rebuttal 本文件包含 ...

  9. 【离线数仓CDH版本】即席查询工具(Presto、Druid、Kylin)、CDH数仓、Impala查询

    1.即席查询 一.Presto 大数据量.秒级.多数据源的查询引擎[支持各种数据源work的内存级查询] 由coordinator和多个work构成,work对应不同数据源Catalog 特点:基于内 ...

  10. Django静态文件配置(from表单-request对象方法-get请求与post请求-视图函数书写)

    目录 一:静态文件配置 1.静态文件配置 2.什么是静态文件? 3.静态文件的创建 4.解决使用django后端代码修改前端不显示(缓存问题) 5.settings.py 静态文件配置 6.静态文接口 ...