浅谈Python中的with,可能有你不知道的
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]
执行过程
对上下文表达式 (在
with_item中给出的表达式) 求值以获得一个上下文管理器。载入上下文管理器的
__enter__()以便后续使用。载入上下文管理器的
__exit__()以便后续使用。发起调用上下文管理器的
__enter__()方法。如果
with语句中包含一个目标,来自__enter__()的返回值将被赋值给它。with语句会保证如果 __enter__()方法返回时未发生错误,则 __exit__()将总是被调用。 因此,如果在对目标列表赋值期间发生错误,则会将其视为在语句体内部发生的错误。 参见下面的第 6 步。
执行语句体。
发起调用上下文管理器的
__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)
- 数传递给
__exit__()。 否则的话,将提供三个None参数
浅谈Python中的with,可能有你不知道的的更多相关文章
- 浅谈python中得import xxx,from xxx import xxx, from xxx import *
在python中import跟from import都是用来导入的,但是导入的机制不同 1.import xxx:导入模块,或者文件夹,对于调用模块或者文件夹中子模块的变量或者函数,需要使用" ...
- 浅谈python中的“ ==” 与“ is”
在python中,== 与 is 之间既有区别,又有联系,本文将通过实际代码的演示,力争能够帮助读到这篇文章的朋友以最短的时间理清二者的关系,并深刻理解它们在内存中的实现机制.扯淡的话不多说,下面马上 ...
- 浅谈python中文件和文件夹的相关操作
文件操作 文件的打开与关闭 打开文件 使用open(文件名,访问方式)函数,可以打开一个已存在的文件,或者创建一个新的文件. 示例如下: f = open('test.txt') # 访问方式可以省略 ...
- 浅谈python中字典append 到list 后值的改变问题
看一个例子 ? 1 2 3 4 d={'test':1} d_test=d d_test['test']=2 print d 如果你在命令行实践的话,会发现你改动的是d_test ,但是d 也跟着改变 ...
- 浅谈python中的闭包函数
闭包函数初探 通常我们定义函数都是这样定义的 def foo(): pass 其实在函数式编程中,函数里面还可以嵌套函数,如下面这样 def foo(): print("hello worl ...
- 浅谈python中的“ ==” 与“ is”、还有cmp
总之,比较内容相等使用 ‘==’ 1.is" 是用来比较 a 和 b 是不是指向同一个内存单元,而"=="是用来比较 a 和 b指向的内存单元中的值是不是相等 2.pyt ...
- 浅谈Python中函数式编程、面向对象编程以及古怪的PythonIC
1.函数式编程作为结构化编程的一种,正在受到越来越多的重视.那么什么事函数式编程呢? 在维基百科中给出了详细的定义,函数式编程又称泛函数编程,是一种编程规范,它将函数运算视为数学上的函数计算.简单的来 ...
- 浅谈python中__str__和__repr__的区别
很多时候我们在创建一个类的时候,在终端打印类或者查看的时候一般都不会得到一个太满意的结果 class T: def __init__(self): self.color="red" ...
- 浅谈Python 中 __getattr__与__getattribute__的区别
__getattr__与__getattribute__均是一般实例属性截取函数(generic instance attribute interception method),其中,__getatt ...
- 浅谈python 中正则的一些函数
主要的函数有 : match() search() findall() group() groups() split() match (): 含义 开头匹配,匹配成功返回一个对象失败则 ...
随机推荐
- java判断手机号三大运营商归属的工具类
package com.tymk.front.third; import java.util.regex.Pattern; public class OperatorsUtil { /** * 中国电 ...
- 【初赛】CSP 2020 第一轮(初赛)模拟记录
感觉初赛不过关,洛谷上找了一套没做过的来练习. 顺便写了详细的题解. 试题用时:1h 单项选择: 第 1 题 十进制数 114 的相反数的 8 位二进制补码是: A.10001110 B.100011 ...
- ironic组件硬件自检服务——ironic-inspector
介绍 ironic-inspector是一个用于硬件自检的辅助型服务,它可以对被ironic组件管理的裸金属节点进行硬件自检,通过在裸金属节点上运行内存系统,发现裸金属节点的硬件信息,例如CPU数量和 ...
- polkit(ploicykit)特权提升漏洞解决方案
一.[概述] polkit 的 pkexec 存在本地权限提升漏洞,已获得普通权限的攻击者可通过此漏洞获取root权限,漏洞利用难度低. pkexec是一个Linux下Polkit里的setuid工具 ...
- Android 按钮自定义背景后点击没有动画效果
只需要在按钮中添加属性就可以了 android:foreground="?selectableItemBackground"
- 移动 VR 开发时要避免的 PC 渲染技术
更新:本文是为 Quest 1 开发人员编写的.虽然 Quest 2 建立在相同的架构上,但现在更容易为阴影贴图(以及其他需要从先前渲染过程中生成的纹理读取的简单技术)做预算. 尽管移动芯片组可以支持 ...
- ajax 获取json值
请求后台获取json: {"success":true,"datamap":{"rebackName":"振勋"}} a ...
- Blazor Server完美实现Cookie Authorization and Authentication
Blazor server-side application用Microsoft.AspNetCore.Identity.EntityFrameworkCore实现Authorization 和 Au ...
- 【Java SE】Day01 前言、入门程序、常量、变量
回顾一下Java之前学的内容 Day01 前言.入门程序.常量.变量 一.基础知识 莱布尼茨发明二进制,辗转相除与8421位权法互转,1B=1bit=1字节=8位=8byte dos cls清屏dir ...
- 【SQL进阶】【分步写、联合各自排序、TIMESTAMPDIFF时间比较】Day04:多表查询
〇.内容 时间比较2-2 联合结果各自排序 查询列和GROUP BY 一.嵌套子查询 1.月均完成试卷数不小于3的用户爱作答的类别 自己的答案[错误]: SELECT tag, COUNT(A.sta ...