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. 类视图函数 VIEW

    常用的视图函数: ListView.DetailView.UpdateView 1 ListView object_list:此属性表示对象的列表 常用场景: 1.展示数据库中信息: 2.在展示信息时 ...

  2. 阿里云 ACK 接入观测云

    简介 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理.2021 年成为国内唯一连续三年入选 Gartner 公共云容器报告的 ...

  3. 10 | Kubernetes一键部署利器:kubeadm

    你好,我是张磊.今天我和你分享的主题是:Kubernetes一键部署利器之kubeadm. 通过前面几篇文章的内容,我其实阐述了这样一个思想:要真正发挥容器技术的实力,你就不能仅仅局限于对Linux容 ...

  4. 深度探索Go语言:包装方法

    问题1:什么是包装方法? 下面咱们来验证下包装方法的存在: 首先,定义一个Point类型,表示一维坐标系内的一个点,并且按照Go语言的风格为其实现了一个Get方法和一个Set方法. package g ...

  5. 支持 equals 相等的对象(可重复对象)作为 WeakHashMap 的 Key

    原文地址 代码地址 问题 长链接场景下通常有一个类似 Map<String, Set<Long>> 的结构,用来查找一个逻辑组内的哪些用户,String 类型的 Entry.k ...

  6. 【Devexpress】gridcontorl设置某个特定单元格不可编辑

    在gridcontorl中一般情况下我们使用的都是设置一列不可编辑 那么如何设置一个单元格不可编辑呢 在gridView1_ShowingEditor事件中可以实现.这个事件的意思是允许取消激活编辑器 ...

  7. python-简单模块的使用

    提示:简单模块了解掌握 @ 目录 uuid模块 calendar日历模块 time模块 datetime模块 os模块 sys模块 random模块 json和pickle模块 json pickle ...

  8. 【Shell案例】【awk每行执行一次】11、转置文件的内容

    描述写一个 bash脚本来转置文本文件nowcoder.txt中的文件内容. 为了简单起见,你可以假设:你可以假设每行列数相同,并且每个字段由空格分隔 示例:假设 nowcoder.txt 内容如下: ...

  9. 缓存管理器CacheManager使用

    缓存管理器CacheManager 一.背景 ​ 代码并发量因建行活动页上升,大量请求打到Mongo导致数据库cpu100%从而服务不可用,目前解决方案,使用编程式缓存,即对缓存的操作与业务代码耦合. ...

  10. Django框架:2、静态文件配置、form表单、request对象、pycharm链接数据库、django链接数据库、ORM框架

    Django框架 目录 Django框架 一.静态文件配置 1.静态文件 2.配置方法 二.form表单 1.action属性 2.method属性 三.request对象 1.基本用法 四.pych ...