在文件处理和网络编程时,对于打开的文件不管最后内容处理是否符合预期都要在结束时关闭文件。这时常见的处理方法是try catch finally 的方法

f = open("demo.txt", "a")

try:
f = open("demo.txt", "a")
raise Exception("读取内容报错")
except Exception as e:
print(e)
finally:
if f is not None:
f.close()

使用错误捕获的方法有效的避免了文件打开没有关闭的情况。实现同样的功能有一种更加优雅的方法,那就是with关键字。

with 语法介绍:

上下文管理器(context manager)是 Python2.5 开始支持的一种语法,用于规定某个对象的使用范围。一旦进入或者离开该使用范围,会有特殊操作被调用。它的语法形式是 with…as…,主要应用场景资源的创建和释放。例如,文件就支持上下文管理器,可以确保完成文件读写后关闭文件句柄。

简单示例如下:

with open("demo.txt", "a+") as f:
print("文件读取")

使用with就可以不用写冗长的try catch finally等处理流程,而且文件一定是安全打开和关闭。with之所以能做到是因为open对象中有打开文件的方法__enter__和关闭文件的方法__exit__,在执行到print之前with调用了__enter__方法,执行完print之后with调用了__exit__方法。并且不管打开文件之后是否会出错,with最终都会调用__eixt__方法。所以文件一定能安全关闭。

with 使用

一个对象想要支持with这种优雅的方法来管理,需要实现__enter____exit__两个方法。根据with是否有返回,可以分成两个类型。

  1. 没有返回值,如with open("demo.txt");
  2. 有返回值,如with open("demo.txt") as f;

没有返回值

class ContextDemo:
def __init__(self):
print("__init__")
return def __enter__(self):
print("__enter__") def __exit__(self, exc_type, exc_val, exc_tb):
print("__exit__") if __name__ == '__main__':
with ContextDemo():
print("我就是with中的操作")
__init__
__enter__
我就是with中的操作
__exit__

有返回值

with 的返回值实际上就是__enter__中return的结果。有return就有返回值,没有return就没有返回值

class ContextDemo:
def __init__(self):
print("__init__")
return def __enter__(self):
print("__enter__")
return 100 def __exit__(self, exc_type, exc_val, exc_tb):
print("__exit__") if __name__ == '__main__':
with ContextDemo() as num :
print(f"我就是with中的操作,输出{num}")
__init__
__enter__
我就是with中的操作,输出100
__exit__

contextlib

contextlib是一个上下文管理器工具,工具中有一个contextmanager,可以将一个函数变成一个装饰器,用来支持with关键字。

通俗来说就是如果一个函数想要支持with就需要有__enter____exit__这两个方法。而contextmanager就可以将函数变成这样一个函数。

依然根据with是否有返回值,区分两中使用方法

不带返回值

from contextlib import contextmanager

@contextmanager
def manager_fun():
print("enter")
yield
print("exit") with manager_fun():
print("我就是with中的操作")
enter
我就是with中的操作
exit

函数中通过yield将函数分成三个部分:yield之前代码、yield之后代码、yield;

执行的流程也是三个步骤:

  1. with manager_fun with 进入时执行yield之前的代码部分 print("enter")
  2. 遇到yield中断,然后执行print("我就是with中的操作")
  3. 最后返回到yield后面,执行print("exit")

传统上下文管理器需要实现的__enter____exit__在contextlib中对应的就是:yield之前代码就是__enter__,yield代码之后就是__exit__

带返回值

from contextlib import contextmanager

@contextmanager
def manager_fun():
print("enter")
yield 100
print("exit") with manager_fun() as num:
print(f"我就是with中的操作{num}")
enter
我就是with中的操作100
exit

with 可以有返回值,如果想实现返回值,在传统上下文管理器中是__enter__函数的返回值就是with的返回值,在contextlib中就是yield的返回值。

yield 返回一个值,然后程序中断暂停在这里。返回的值就是with的返回值。(听起来有点绕口)

contextlib 使用场景

有些场景下想要使用with来管理对象,但是目标对象并不支持,这时就可以通过contextlib来包装一个上下文管理器,达到管理资源的目的

Python上下文管理器的高级使用的更多相关文章

  1. Python上下文管理器

    在Python中让自己创建的函数.类.对象支持with语句,就实现了上线文管理协议.我们经常使用with open(file, "a+") as f:这样的语句,无需手动调用f.c ...

  2. python 上下文管理器

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 上下文管理器(context manager)是Python2.5开始支持的一种语 ...

  3. Python 上下文管理器和else块

    最终,上下文管理器可能几乎与子程序(subroutine)本身一样重要.目前,我们只了解了上下文管理器的皮毛--Basic 语言有with 语句,而且很多语言都有.但是,在各种语言中 with 语句的 ...

  4. python上下文管理器ContextLib及with语句

    http://blog.csdn.net/pipisorry/article/details/50444736 with语句 with语句是从 Python 2.5 开始引入的一种与异常处理相关的功能 ...

  5. Python上下文管理器 with

    对于系统资源的操作,如:文件操作.数据库操作等,我们往往打开文件.连接数据库后忘了将其close掉,这时就可能会引发异常,因此我们常用的做法是: # coding:utf-8 f = open(&qu ...

  6. Python上下文管理器(Context managers)

    上下文管理器(Context managers) 上下文管理器允许你在有需要的时候,精确地分配和释放资源. 使用上下文管理器最广泛的案例就是with语句了.想象下你有两个需要结对执行的相关操作,然后还 ...

  7. python上下文管理器细读

    test 1 上下文管理器,将生成器转化为上下文管理器 import contextlib @contextlib.contextmanager def a(): print(1) yield pri ...

  8. 吃透Python上下文管理器

    什么是上下文管理器? 我们常见的with open操作文件,就是一个上下文管理器.如: with open(file, 'rb') as f: text = f.read() 那上下文管理器具体的定义 ...

  9. python 上下文管理器contextlib.ContextManager

    1 模块简介 在数年前,Python 2.5 加入了一个非常特殊的关键字,就是with.with语句允许开发者创建上下文管理器.什么是上下文管理器?上下文管理器就是允许你可以自动地开始和结束一些事情. ...

  10. Python 上下文管理器模块--contextlib

    在 Python 处理文件的时候我们使用 with 关键词来进行文件的资源关闭,但是并不是只有文件操作才能使用 with 语句.今天就让我们一起学习 Python 中的上下文管理 contextlib ...

随机推荐

  1. Android 11 使用 BroadcastReceiver 监听短消息

    使用装有MIUI系统的小米手机,静态注册的广播接收器监听短消息. 在AndroidManifest.xml中声明权限 <uses-permission android:name="an ...

  2. Kubernetes 漫游:etcd

    概述 etcd 是一个基于 Raft 协议实现.开源的.分布式的键值存储系统.主要用于在分布式系统中提供强一致性和高可用性的数据存储. etcd 在 Kubernetes 中的作用如下: 集群状态数据 ...

  3. 深入了解HMAC加密技术:原理、应用与实践

    一.引言 在网络安全领域,消息认证码(MAC)是一种重要的技术手段.Hash-based Message Authentication Code(HMAC)作为其中的一种,凭借其简单.高效.安全的特性 ...

  4. 25 个超棒的 Python 脚本合集

    Python是一种功能强大且灵活的编程语言,拥有广泛的应用领域.下面是一个详细介绍25个超棒的Python脚本合集: 1. 网络爬虫:使用Python可以轻松编写网络爬虫,从网页中提取数据并保存为结构 ...

  5. .net 获取客户端真实ip

    Nginx 如何设置 情况1 在只有1层nginx代理的情况下,设置nginx配置"proxy_set_header X-Forwarded-For $remote_addr;". ...

  6. VCS用法

    1.时钟频率点击,鼠标左键点击波形上升沿,中间滚轮点击,然后选择hz,就显示当前信号时钟频率. 2.窗口乱掉,找不到文件列表,右下角点击弹出选择instance. 3.bus地址查找,选择信号,然后蓝 ...

  7. 如何编写一个 Pulsar Broker Interceptor 插件

    背景 之前写过一篇文章 VictoriaLogs:一款超低占用的 ElasticSearch 替代方案讲到了我们使用 Victorialogs 来存储 Pulsar 消息队列的消息 trace 信息. ...

  8. 使用FRP实现内网穿透<阿里云服务器端+WINDOWS客户端>

    使用FRP实现内网穿透 1.准备条件 一个云服务器 一个FRP服务端文件,下载地址 一个FRP的windows客户端文件,下载地址 2.服务端 使用远程客户端工具,连接你自己的云服务器(我使用的是阿里 ...

  9. LeetCode190:颠倒二进制(位运算分治! 时间复杂度O(1))

    解题思路:这道题很两种解法,常规的就是O(n),另一种就是巧妙的利用位运算实现分治,时间复杂度O(1),类似于归并排序.不过这个递归不是自顶向下,而是巧用位运算从自底向上实现. 比如01001000通 ...

  10. 数据智慧:C#中编程实现自定义计算的Excel数据透视表

    前言 数据透视表(Pivot Table)是一种数据分析工具,通常用于对大量数据进行汇总.分析和展示.它可以帮助用户从原始数据中提取关键信息.发现模式和趋势,并以可视化的方式呈现. 在数据透视表中,数 ...