阅读目录

在实际的编码过程中,有时有一些任务,需要事先做一些设置,事后做一些清理,这时就需要python with出场了,with能够对这样的需求进行一个比较优雅的处理,最常用的例子就是对访问文件的处理。

一般访问文件资源时我们会这样处理:

--------------------------------------------------------------------
注:如果你对python感兴趣,我这有个学习Python基地,里面有很多学习资料,感兴趣的+Q群:895817687
--------------------------------------------------------------------f = open(r'c:\test.txt', 'r')
data = f.read()
f.close()

这样写没有错,但是容易犯两个毛病:

  1. 如果在读写时出现异常而忘了异常处理。
  2. 忘了关闭文件句柄

以下的加强版本的写法:

    f = open(r'c:\test.txt', 'r')try:data = f.read()finally:f.close()

以上的写法就可以避免因读取文件时异常的发生而没有关闭问题的处理了。代码长了一些。
但使用with有更优雅的写法:

    with open(r'c:\test.txt', 'r') as f:data = f.read()

说明:
with后面接的对象返回的结果赋值给f。此例当中open函数返回的文件对象赋值给了f.with会自已获取上下文件的异常信息。
with是如何做到的呢?
with后面返回的对象要求必须两__enter__()/exit()这两个方法,而文件对象f刚好是有这两个方法的,故应用自如。
pytho中官方定义说明如下(https://docs.python.org/2/reference/datamodel.html#context-managers):

object.__enter__(self)
进入与此对象相关的运行时上下文。with语句将将此方法的返回值绑定到语句的AS子句中指定的目标(如果有设置的话)object.__exit__(self, exc_type, exc_value, traceback)
退出与此对象相关的运行时上下文。参数描述导致上下文退出的异常。如果上下文运行时没有异常发生,那么三个参数都将置为None。
如果有异常发生,并且该方法希望抑制异常(即阻止它被传播),则它应该返回True。否则,异常将在退出该方法时正常处理。请注意, __exit__()方法不应该重新抛出传入的异常,这是调用者的职责。

所谓上下文管理协议,就是咱们打开文件时常用的一种方法:with

enter(self):当with开始运行的时候触发此方法的运行

exit(self, exc_type, exc_val, exc_tb):当with运行结束之后触发此方法的运行

exc_type如果抛出异常,这里获取异常的类型

exc_val如果抛出异常,这里显示异常内容

exc_tb如果抛出异常,这里显示所在位置

下面举例说明他的原理:

  1. 无异常发生时的例子:
#!/user/bin/env python3
#-*- coding:utf-8 -*-class Test:def __enter__(self):print('__enter__() is call!')return selfdef dosomething(self):print('dosomethong!')def __exit__(self, exc_type, exc_value, traceback):print('__exit__() is call!')print(f'type:{exc_type}')print(f'value:{exc_value}')print(f'trace:{traceback}')print('__exit()__ is call!')with Test() as sample:sample.dosomething()>>
__enter__() is call!
dosomethong!
__exit__() is call!
type:None
value:None
trace:None
__exit()__ is call!

以上的实例Text,我们注意到他带有__enter__()/exit()这两个方法,当对象被实例化时,就会主动调用__enter__()方法,任务执行完成后就会调用__exit__()方法,另外,注意到,exit()方法是带有三个参数的(exc_type, exc_value, traceback), 依据上面的官方说明:如果上下文运行时没有异常发生,那么三个参数都将置为None, 这里三个参数由于没有发生异常,的确是置为了None, 与预期一致.

  1. 有异常发生时,会抛出异常的例子:
    以下例子在上面稍做了一些修改,让运行时产生异常,看看这三个参数的赋值情况:
#!/user/bin/env python3
#-*- coding:utf-8 -*-class Test:def __enter__(self):print('__enter__() is call!')return selfdef dosomething(self):x = 1/0print('dosomethong!')def __exit__(self, exc_type, exc_value, traceback):print('__exit__() is call!')print(f'type:{exc_type}')print(f'value:{exc_value}')print(f'trace:{traceback}')print('__exit()__ is call!')# return Truewith Test() as sample:sample.dosomething()
>>
__enter__() is call!
Traceback (most recent call last):
__exit__() is call!
type:<class 'ZeroDivisionError'>File "C:/Users/xxx/PycharmProjects/Test1/test.py", line 23, in <module>
value:division by zerosample.dosomething()
trace:<traceback object at 0x000001C08CF32F88>File "C:/Users/xxx/PycharmProjects/Test1/test.py", line 10, in dosomething
__exit()__ is call!x = 1/0
ZeroDivisionError: division by zero

从结果可以看出, 在执行到dosomethong时就发生了异常,然后将异常传给了__exit__(), 依据上面的官方说明:如果有异常发生,并且该方法希望抑制异常(即阻止它被传播),则它应该返回True。否则,异常将在退出该方法时正常处理。当前__exit__并没有写明返回True,故会抛出异常,也是合理的,但是正常来讲,程序应该是不希望它抛出异常的,这也是调用者的职责,我们将再次修改__exit__, 将其返回设置为True,

  1. 有异常发生时,不再抛出异常的例子:
# 在上面的例子上做点修改.
#!/user/bin/env python3
#-*- coding:utf-8 -*-class Test:def __enter__(self):print('__enter__() is call!')return selfdef dosomething(self):x = 1/0print('dosomethong!')def __exit__(self, exc_type, exc_value, traceback):print('__exit__() is call!')print(f'type:{exc_type}')print(f'value:{exc_value}')print(f'trace:{traceback}')print('__exit()__ is call!')return Truewith Test() as sample:sample.dosomething()>>
__enter__() is call!
__exit__() is call!
type:<class 'ZeroDivisionError'>
value:division by zero
trace:<traceback object at 0x000001C94E592F88>
__exit()__ is call!

从结果看,异常抛出被抑制了,符合预期。

python with方法相关推荐

  1. Python ljust()方法

    描述 Python ljust() 方法返回一个原字符串左对齐,并使用空格填充至指定长度的新字符串.如果指定的长度小于原字符串的长度则返回原字符串. 语法 ljust()方法语法: str.ljust ...

  2. Python join()方法

    描述 Python join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串. 语法 join()方法语法: str.join(sequence).join(sequence) 参数 s ...

  3. Python maketrans() 方法

    描述 Python maketrans() 方法用于给 translate() 方法创建字符映射转换表. 可以只接受一个参数,此时这个参数是个字典类型(暂不研究这种情况). 对于接受两个参数的最简单的 ...

  4. python count()方法

    Python count() 方法 | 菜鸟教程 可以统计一个字符串里含有子字符串的个数  频次

  5. Python rstrip()方法 删除 string 字符串末尾的指定字符(默认为空格).

    Python rstrip()方法  Python 字符串 描述 Python rstrip() 删除 string 字符串末尾的指定字符(默认为空格). 语法 rstrip()方法语法: str.r ...

  6. vscode使用教程python-如何在VSCode上轻松舒适的配置Python的方法步骤

    前言 之前被学长推荐使用了VSCode,后惊叹了VSCode的强大,尤其是他的配置,比之前使用sublime方便多了,刚好实验室也来了一批新的学弟学妹,来仔细的逐步的讲解一些,在自己的电脑上轻松的配置 ...

  7. 自学python方法-总算懂得快速学习python的方法

    随着Python的进一步发展,越来越多的现成的Python的机器学习的算法已经发布出来.为了可以更好地运用这些机器学习的算法,我们有必要对Python有个初步的了解.以下是小编为你整理的快速学习pyt ...

  8. python类中方法的执行顺序-浅谈Python的方法解析顺序(MRO)

    方法解析顺序, Method Resolution Order 从一段代码开始 考虑下面的情况: class A(object): def foo(self): print('A.foo()') cl ...

  9. Python 字符串方法详解

    Python 字符串方法详解 本文最初发表于赖勇浩(恋花蝶)的博客(http://blog.csdn.net/lanphaday),如蒙转载,敬请保留全文完整,切勿去除本声明和作者信息. 在编程中,几 ...

  10. vscode 调试python 无法连接远程服务器_vscode 远程调试python的方法

    此文介绍了vscode 远程调试python的方法,分享给大伙,具有如下: 实验环境 远程服务器:京东云,1核2G,centos7.3 64bit 本地环境配置 安装vscode,实验用的版本是1.1 ...

最新文章

  1. [Notice]博客地址转移 vitostack.com
  2. 高德地图2020最新版下载导航wince_导航定位错误致青城山严重拥堵,高德地图回应:已优化...
  3. python面向对象(2)—— 继承(3)
  4. Akka的字数统计MapReduce
  5. 数据库系统内部体系结构与外部体系结构
  6. HDU-2332 机器人的舞蹈 递推
  7. linux hive的作用,Hive的基本应用 - Hadoop和Hive的实践应用_服务器应用_Linux公社-Linux系统门户网站...
  8. 谷歌手机Nexus和Pixel系列研发代号
  9. learning - Haskell AND Lisp vs. Haskell OR Lisp - Programmers Stack Exchange
  10. python基础: 序列
  11. Java -- JSP面试题及答案
  12. bat篇---windows bat启动exe结尾的可执行程序
  13. 搜索优化之四叉树算法(三)
  14. CentOS安装配置freeIPA
  15. Codeforces Round #469 (Div. 2) F. Curfew
  16. 逆向工程实验——lab8(C/C++反逆向、Java字节码反逆向)
  17. 怎么制作书单视频?免费制作书单视频软件分享
  18. 【Codeforces Round #548(Div. 2)】Edgy Trees(数学+bfs求连通块)
  19. 关于人工智能不会使大脑变懒惰的议论文_人工智能的好处和风险:所有您需要知道的...
  20. JavaWeb-02

热门文章

  1. 01 | 顶层设计:微服务生态与 Spring Cloud Alibaba
  2. 牛客题霸 NC20 数字字符串转化成IP地址
  3. 《Java程序设计》实验报告——Java的接口与继承
  4. Prefix Sum Primes
  5. Diverse Strings
  6. linux下php的安装路径,Linux下Apache、PHP、MySQL默认安装路径
  7. 操作系统 课堂练习题02【8道 经典题目】
  8. JavaScript学习笔记01【基础——简介、基础语法、运算符、特殊语法、流程控制语句】
  9. ConcurrentHashMap源码学习
  10. MyBatis之PageHelper分页操作