Python中with上下文管理协议的作用及用法


Posted in Python onMarch 18, 2022

1、简介

       with是从Python2.5引入的一个新的语法,它是一种上下文管理协议,目的在于从流程图中把 try,except 和finally 关键字和资源分配释放相关代码统统去掉,简化try…except…finlally的处理流程。

       那我们先理解一下try…except…finally语句是干啥的。实际上,try…except语句和try…finally语句是两种语句,用于不同的场景。但是当二者结合在一起时,可以“实现稳定性和灵活性更好的设计”。

2、try… except语句

       用于处理程序执行过程中的异常情况,比如语法错误、从未定义变量上取值等等,也就是一些python程序本身引发的异常、报错。而try… except语句就是为了防止一些报错影响你的程序继续运行,就用try语句把它们抓出来(捕获)。

(1)try…except的标准格式

try:  
    ## normal block  
except A:  
    ## exc A block  
except:  
    ## exc other block  
else:  

(2)程序执行流程

–>执行normal block
–>发现有A错误,执行 exc A block(即处理异常)
–>结束
如果没有A错误呢?
–>执行normal block
–>发现B错误,开始寻找匹配B的异常处理方法,发现A,跳过,发现except others(即except:),执行exc other block
–>结束
如果没有错误呢?
–>执行normal block
–>全程没有错误,跳入else 执行noError block
–>结束

(3)异常分类

       except后面还能跟表达式的! 所谓的表达式,就是错误的定义。也就是说,我们可以捕捉一些我们想要捕捉的异常。而不是什么异常都报出来。

异常分两类:

  • python标准异常
  • 自定义异常

(a)Python标准异常

      Python标准异常包括NameError(未声明/初始化对象,没有属性),MemoryError内存溢出错误等错误,

详细python标准异常详见:

异常名称 描述
BaseException 所有异常的基类
SystemExit 解释器请求退出
KeyboardInterrupt 用户中断执行(通常是输入^C)
Exception 常规错误的基类
StopIteration 迭代器没有更多的值
GeneratorExit 生成器(generator)发生异常来通知退出
StandardError 所有的内建标准异常的基类
ArithmeticError 所有数值计算错误的基类
FloatingPointError 浮点计算错误
OverflowError 数值运算超出最大限制
ZeroDivisionError 除(或取模)零 (所有数据类型)
AssertionError 断言语句失败
AttributeError 对象没有这个属性
EOFError 没有内建输入,到达EOF 标记
EnvironmentError 操作系统错误的基类
IOError 输入/输出操作失败
OSError 操作系统错误
WindowsError 系统调用失败
ImportError 导入模块/对象失败
LookupError 无效数据查询的基类
IndexError 序列中没有此索引(index)
KeyError 映射中没有这个键
MemoryError 内存溢出错误(对于Python 解释器不是致命的)
NameError 未声明/初始化对象 (没有属性)
UnboundLocalError 访问未初始化的本地变量
ReferenceError 弱引用(Weak reference)试图访问已经垃圾回收了的对象
RuntimeError 一般的运行时错误
NotImplementedError 尚未实现的方法
SyntaxError Python 语法错误
IndentationError 缩进错误
TabError Tab 和空格混用
SystemError 一般的解释器系统错误
TypeError 对类型无效的操作
ValueError 传入无效的参数
UnicodeError Unicode 相关的错误
UnicodeDecodeError Unicode 解码时的错误
UnicodeEncodeError Unicode 编码时错误
UnicodeTranslateError Unicode 转换时错误
Warning 警告的基类
DeprecationWarning 关于被弃用的特征的警告
FutureWarning 关于构造将来语义会有改变的警告
OverflowWarning 旧的关于自动提升为长整型(long)的警告
PendingDeprecationWarning 关于特性将会被废弃的警告
RuntimeWarning 可疑的运行时行为(runtime behavior)的警告
SyntaxWarning 可疑的语法的警告
UserWarning 用户代码生成的警告

例:

  try:
        a = 1 / 2
        print(a)
        print(m)  # 此处抛出python标准异常
        b = 1 / 0  # 此后的语句不执行
        print(b)
        c = 2 / 1
        print(c)
    except NameError:
        print("Ops!!")
    except ZeroDivisionError:
        print("Wrong math!!")
    except:
        print("Error")

输出:

Python中with上下文管理协议的作用及用法

3、try…finallly语句

       try…finallly语句用于无论执行过程中有没有异常,都要执行清场工作。

格式:

try:  
    execution block  ##正常执行模块  
except A:  
    exc A block ##发生A错误时执行  
except B:  
    exc B block ##发生B错误时执行  
except:  
    other block ##发生除了A,B错误以外的其他错误时执行  
else:  
    if no exception, jump to here ##没有错误时执行  
finally:  
final block  ##总是执行  

tips: 注意顺序不能乱,否则会有语法错误。如果用else就必须有except,否则会有语法错误。

例:   

 try:
        a = 1 / 2
        print(a)
        print(m)  # 抛出NameError异常
        b = 1 / 0
        print(b)
        c = 2 / 1
        print(c)
    except NameError:
        print("Ops!!")  # 捕获到异常
    except ZeroDivisionError:
        print("Wrong math!!")
    except:
        print("Error")
    else:
        print("No error! yeah!")
    finally:  # 是否异常都执行该代码块
        print("finally!")

输出:

Python中with上下文管理协议的作用及用法

4、with…as语句

(1)With语句的基本语法

       with通过__enter__方法初始化,然后在__exit__中做善后以及处理异常。其中__enter__()方法在语句体(with语句包裹起来的代码块)执行之前进入运行,__exit__()方法在语句体执行完毕退出后运行。

       with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。

With语句的基本语法格式:

with expression [as target]:
with-block  
  • expression:是一个需要执行的表达式;
  • target:是一个变量或者元组,存储的是expression表达式执行返回的结果,可选参数。

(2)with语句原理

  • 上下文管理协议(Context Management Protocol):包含方法 __enter__()和__exit__(),支持该协议的对象要实现这两个方法。
  • 上下文管理器(Context Manager):支持上下文管理协议的对象,这种对象实现了__enter__()和__exit__()方法。上下文管理器定义执行with语句时要建立的运行时上下文,负责执行with语句块上下文中的进入与退出操作。通常使用with语句调用上下文管理器,也可以通过直接调用其方法来使用。

例:执行过程

with EXPR as VAR:
    BLOCK

(1)执行EXPR,生成上下文管理器context_manager

(2)获取上下文管理器的__exit()__方法,并保存起来用于之后的调用;

(3)调用上下文管理器的__enter__()方法;如果使用了as子句,则将__enter__()方法的返回值赋值给as子句中的VAR;

(4)执行BLOCK中的表达式;

(5)不管是否执行过程中是否发生了异常,执行上下文管理器的__exit__()方法,__exit__()方法负责执行“清理”工作,如释放资源等。如果执行过程中没有出现异常,或者语句体中执行了语句break/continue/return,则以None作为参数调用__exit__(None, None, None);如果执行过程中出现异常,则使用sys.exc_info得到的异常信息为参数调用__exit__(exc_type, exc_value, exc_traceback);

(6)出现异常时,如果__exit__(type, value, traceback)返回False,则会重新抛出异常,让with之外的语句逻辑来处理异常,这也是通用做法;如果返回True,则忽略异常,不再对异常进行处理。

这个和try finally函数有什么关系呢?其实,这样的过程等价于:

try:  
    执行 __enter__的内容  
    执行 with_block.  
finally:  
    执行 __exit__内容  

例:

class Sample(object):
 
    def __init__(self):
        print("__init__")
 
    def __enter__(self):
        print("__enter__")
 
    def __exit__(self, types, values, trace):
        print("type:", types)
        print("value:", values)
        print("trace:", trace)
 
 
def get_sample():
    return Sample()
 
 
if __name__ == '__main__':
    # get_data()
    with get_sample() as sample:
        print("Sample:", sample)

输出:

Python中with上下文管理协议的作用及用法

到此这篇关于Python中with上下文管理协议的作用及用法的文章就介绍到这了,更多相关Python中with用法内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!               

Python 相关文章推荐
linux系统使用python监测系统负载脚本分享
Jan 15 Python
Python入门篇之正则表达式
Oct 20 Python
Python类方法__init__和__del__构造、析构过程分析
Mar 06 Python
Python学习教程之常用的内置函数大全
Jul 14 Python
python自动登录12306并自动点击验证码完成登录的实现源代码
Apr 25 Python
Opencv-Python图像透视变换cv2.warpPerspective的示例
Apr 11 Python
详解PANDAS 数据合并与重塑(join/merge篇)
Jul 09 Python
Python Selenium安装及环境配置的实现
Mar 17 Python
Django ModelForm操作及验证方式
Mar 30 Python
python数据类型强制转换实例详解
Jun 22 Python
Python基础教程之输入输出和运算符
Jul 26 Python
PySwarms(Python粒子群优化工具包)的使用:GlobalBestPSO例子解析
Apr 05 Python
python 判断文件或文件夹是否存在
Mar 18 #Python
分享Python获取本机IP地址的几种方法
Mar 17 #Python
使用python求解迷宫问题的三种实现方法
Python超详细分步解析随机漫步
yolov5返回坐标的方法实例
Mar 17 #Python
PyTorch中的torch.cat简单介绍
Mar 17 #Python
Python Pygame实战在打砖块游戏的实现
You might like
php多重接口的实现方法
2015/06/20 PHP
php实现CSV文件导入和导出
2015/10/24 PHP
PHP图像识别技术原理与实现
2016/10/27 PHP
Thinkphp5 微信公众号token验证不成功的原因及解决方法
2017/11/12 PHP
ThinkPHP5.1的权限控制怎么写?分享一个AUTH权限控制
2021/03/09 PHP
JavaScript内核之基本概念
2011/10/21 Javascript
js 金额文本框实现代码
2012/02/14 Javascript
JS中图片缓冲loading技术的实例代码
2013/08/29 Javascript
jqueryUI里拖拽排序示例分析
2015/02/26 Javascript
js实现iframe框架取值的方法(兼容IE,firefox,chrome等)
2015/11/26 Javascript
Javascript原型链的原理详解
2016/01/05 Javascript
javascript中FOREACH数组方法使用示例
2016/03/01 Javascript
JS提示:Uncaught SyntaxError:Unexpected token ) 错误的解决方法
2016/08/19 Javascript
前端实现文件的断点续传(前端文件提交+后端PHP文件接收)
2016/11/04 Javascript
概述javascript在Google IE中的调试技巧
2016/11/24 Javascript
jQuery插件HighCharts绘制的基本折线图效果示例【附demo源码下载】
2017/03/07 Javascript
基于Vue开发数字输入框组件
2017/12/19 Javascript
微信小程序scroll-view仿拼多多横向滑动滚动条
2020/04/21 Javascript
JS实现的简单分页功能示例
2018/08/23 Javascript
原生JS实现前端本地文件上传
2018/09/08 Javascript
微信小程序下拉框功能的实例代码
2018/11/06 Javascript
详解mpvue实现对苹果X安全区域的适配
2019/07/31 Javascript
微信小程序点击顶部导航栏切换样式代码实例
2019/11/12 Javascript
JavaScript实现文件下载并重命名代码实例
2019/12/12 Javascript
[03:11]DOTA2上海特锦赛小组赛第一日recap精彩回顾
2016/02/28 DOTA
python实现祝福弹窗效果
2019/04/07 Python
详解Python绘图Turtle库
2019/10/12 Python
详解如何用python实现一个简单下载器的服务端和客户端
2019/10/28 Python
在echarts中图例legend和坐标系grid实现左右布局实例
2020/05/16 Python
Django实现随机图形验证码的示例
2020/10/15 Python
Lands’ End英国官方网站:高质量男女服装
2017/10/07 全球购物
运动会稿件50字
2014/02/17 职场文书
2016公司年会通知范文
2015/04/25 职场文书
担保书怎么写 ?
2019/04/22 职场文书
2019关于实习生工作安排及待遇的管理方案!
2019/07/16 职场文书
vue @ ~ 相对路径 路径别名设置方式
2022/06/05 Vue.js