中企动力设计的网站,免费空间可以上传网站吗,电商数据,网页设计教程这本书讲什么DAY 23. python上下文管理器 Python 的 with 语句支持通过上下文管理器所定义的运行时上下文这一概念。 此对象的实现使用了一对专门方法#xff0c;允许用户自定义类来定义运行时上下文#xff0c;在语句体被执行前进入该上下文#xff0c;并在语句执行完毕时退出该上下文允许用户自定义类来定义运行时上下文在语句体被执行前进入该上下文并在语句执行完毕时退出该上下文 实现了__enter__()和__exit__(exc_type, exc_val, exc_tb)方法的对象就是上下文管理器上下文管理器可以被with支持。
class Demo:def __init__(self):print(init)def __enter__(self):print(enter)def __exit__(self, exc_type, exc_val, exc_tb):print(exit)if __name__ __main__:demo Demo()with demo:print(with)
__enter__()的返回值将会赋值给与with配套使用的as后面的变量__exit__()如果返回True会忽略with中抛出的所有异常返回False默认会向下传递异常,三个参数exc_type, exc_val, exc_tb分别表示捕捉到的异常类型异常值回溯信息没有异常为None。其行为类似于try,finally语句不管有没有产生异常exit一定会被执行。
class Demo:def __init__(self):print(init)def __enter__(self):print(enter)return selfdef __exit__(self, exc_type, exc_val, exc_tb):print(exc_type, exc_val, exc_tb)print(exit)if __name__ __main__:demo Demo()with demo as d:print(d)raise IOError(主动抛出异常)print(with)
结果
Traceback (most recent call last):
initFile E:/桌面文件/笔记/Note/Python/总结/code/DAY23/DAY23_1.py, line 18, in module
enterraise IOError(主动抛出异常)
__main__.Demo object at 0x00000243B4005908
OSError: 主动抛出异常
class OSError 主动抛出异常 traceback object at 0x00000243BAEDD048
exit__exit__() return True后的运行结果
init
enter
__main__.Demo object at 0x00000183AFDA11D0
class OSError 主动抛出异常 traceback object at 0x00000183B6E6F908
exit传入的异常绝对不应当被显式地重新引发 —— 相反地此方法应当返回一个假值以表明方法已成功完成并且不希望屏蔽被引发的异常. 这允许上下文管理代码方便地检测 __exit__() 方法是否确实已失败。 generator与contextlib.contextmanager Python 的 generator 和 contextlib.contextmanager 装饰器提供了实现这些协议的便捷方式。 如果使用 contextlib.contextmanager 装饰器来装饰一个生成器函数它将返回一个实现了必要的 __enter__() and __exit__() 方法的上下文管理器而不再是由未经装饰的生成器函数所产生的迭代器。 contextlib.contextmanager 是一个装饰器它可以不用定义类或__enter__()和__exit__(exc_type, exc_val, exc_tb)方法而产生一个上下文管理器,被装饰的函数必须是一个生成器对象并且这个迭代器只能yield出一个对象它会被绑定到with语句as后面的变量上
from contextlib import contextmanagercontextmanager
def my_open(path: str, mode: str):# 之所以之捕捉了yield语句的异常是因为我们只希望如果with语句块中# 产生了异常也可以确保close()被执行至于open可能抛出的异常我们希望它# 能够向下传递。fp open(path, mode)try:yield ffinally:print(close the file)fp.close()if __name__ __main__:with my_open(01.txt, w) as fp:raise OSErrorfp.write(111)
代码执行顺序是
执行yield之前的语句yield调用后执行with中的代码块最后执行yield之后的语句
closing()
closing()是contextlib中的一个方法用来把一个不是上下文对象的方法变成上下文对象,也是用contextmanage实现的一个官方的栗子
from contextlib import closing
from urllib.request import urlopenwith closing(urlopen(http://www.python.org)) as page:for line in page:print(line)不用显式调用page.close()也能确保执行
suppress()
可以选择禁止一个或多个异常
if __name__ __main__:with suppress(OSError):with my_open(01.txt, r) as fp:# 抛出的这个异常会被忽略raise OSErrorfp.write(111)redirect_stdout/redirect_stderr
重定向输入输出
# 将输出重定向到文件from contextlib import redirect_stdoutpath test/test.txtwith open(path,w) as fobj:with redirect_stdout(fobj):help(open)