目录

示例1:查看上下文执行的顺序
示例2:动态控制上下文是否抛出异常
示例3:以装饰器的方式为功能函数加装上下文
示例4:过滤异常,不抛出

  在之前我们进行过文件操作的学习时,我们为了不忘掉文件操作完毕后关闭文件file.close(),官方推荐推荐我们使用with……as 语句,这其实本质就是运用了python的上下文管理。

而所谓的上下文,其实就是服务运行的状态从进入到退出的一种过程,python中我们常常通过上下文来进行资源的创建与释放。

语法:with……as

本质:

程序执行with中的代码时,会自动先执行enter方法,返回在这个上下文中使用的对象句柄,程序执行完逻辑后自动调用exit来进行资源的释放

示例1:查看上下文执行的顺序

如果上下文中出现异常即执行逻辑代码过程中,上下文是可以捕获异常的,并且默认是抛出异常的

class MyContext:   def __init__(self):       print("in __init__")   def __enter__(self):       print("int __enter__")       return self   def __exit__(self, exc_type, exc_val, exc_tb):       """"""       print("in __exit__")       print("异常的类型exc_type=", exc_type)       print("异常抛出的值exc_type=", exc_val)       print("异常的traceback对象exc_type=", exc_tb)if __name__ == '__main__':   with MyContext() as t:       print("执行代码逻辑……")       raise Exception("错误解释")# 执行结果为"""in __init__int __enter__执行代码逻辑……in __exit__异常的类型exc_type= <class 'Exception'>异常抛出的值exc_type= 错误解释异常的traceback对象exc_type= <traceback object at 0x000001B52B5465C8>Traceback (most recent call last):File "D:/my_all_project/Frame_learning/test.py", line 27, in <module>  raise Exception("错误解释")Exception: 错误解释"""

示例2:动态控制上下文是否抛出异常
如果功能函数逻辑中出现异常,而exit方法返回值等价于False就会抛出异常,否则不抛出异常,继续执行上下文外面的业务逻辑

class MyContext:   def __init__(self, flag):       print("in __init__")       self.flag = flag   def __enter__(self):       print("int __enter__")       "可以返回我们定义任何方法或实例化的对象"       return self   def __exit__(self, exc_type, exc_val, exc_tb):       """"""       print("in __exit__")       print("异常的类型exc_type=", exc_type)       print("异常抛出的值exc_type=", exc_val)       print("异常的traceback对象exc_type=", exc_tb)       return self.flagif __name__ == '__main__':   with MyContext(True) as t:       print("执行代码逻辑……")       raise Exception("错误解释")   print("===>当上下文不抛出异常时,此处可以被打印")# t 实际就是类Mycontext的实例化对象,其可以调用类中的任意实例方法和属性

示例3:以装饰器的方式为功能函数加装上下文

import contextlibclass MyContext(contextlib.ContextDecorator):   def __init__(self):       print(f'__init__()')   def __enter__(self):       print(f'__enter__()')       return self   def __exit__(self, exc_type, exc_val, exc_tb):       print(f'__exit__()')       print(f"exc_type:{exc_type}")       try:           self.write_log()       except Exception as e:           print(e)   @staticmethod   def write_log():       print("开始记录日志")       log = dict(req_body="request", rsp_body="response")       f = open("my_log_test.txt", "w", encoding="utf-8")       import json       f.write(json.dumps(log, ensure_ascii=False))       f.flush()       f.close()       raise Exception("本日志记录报错,不在影响功能函数的正常返回")@MyContext()def func(flag):   code, desc = 1, "fail"   try:       if flag:           raise Exception("测试上下文是否能捕获异常")       else:           code, desc = 0, "success"   except Exception as e:       print(f"本初捕获异常:{e},则不会再抛给上下文管理器中")   else:       code, desc = 0, "success"   finally:       return {"code": code, "desc": desc}if __name__ == '__main__':   ret = func(True)   print(ret)# 本小例是通过上下文初试为功能函数添加记录日志的功能,不因记录日志出现异常导致功能函数异常,也可以加一个开关,是否记录日志# 写日志的另一个版本import threadingclass WriteLogContext:   def __init__(self, flag, data):       """      :param flag: 异常日志是否抛出开关标识      :param data: 日志内容      """       self.flag = flag       self.data = data   def __enter__(self):       return self   def __exit__(self, exc_type, exc_val, exc_tb):       print("异常的类型exc_type=", exc_type)       print("异常抛出的值exc_type=", exc_val)       print("异常的traceback对象exc_type=", exc_tb)       return self.flag   def write_action(self):       """开启多线程记录日志,发现异常不会抛出外层,但会将异常打印到控制台"""       write_external_thread = threading.Thread(target=self.write_log, args=(self.data,))       write_external_thread.setDaemon(True)       write_external_thread.start()   @staticmethod   def write_log(log):       with open("test.txt", "a") as file:           file.write("入库的操作模拟\n")           file.write(f"{log}\n")           file.flush()       # 模拟异常       raise TypeError("模拟写日志过程中的异常,发现本处报错,并不会影响主功能函数响应")def access():   # 执行业务   print("business is begin")   # 记录流水   log = "life is short ,i use python ,i use it for make money"   with WriteLogContext(flag=True, data=log) as f:       f.write_action()   # 响应   result = "business is success"   return result

示例4:过滤异常,不抛出

import contextlibdef write_log(data):   if data:       print(111111)   else:       raise Exception("life")with contextlib.suppress(Exception):   data = dict()   write_log(data)# suppress类可以过滤指定的异常,不抛出
©著作权归作者所有:来自51CTO博客作者mob604756e88498的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 立即执行函数 箭头函数等
  2. js引入方式、变量与常量的声明与使用方式、函数与高阶函数,实例演
  3. 什么是CPU 上下文切换
  4. php pdo 插入中文出现乱码解决 办法
  5. javascript:引入方式/变量与常量声明/函数与高阶函数/归并参数/箭
  6. MyBatis的SQL执行流程,逻辑超清晰,总结得也太全了吧!
  7. redis事务,分布式锁
  8. 数据调度组件:基于Azkaban协调时序任务执行
  9. shell脚本语句语法使用(超详细)

随机推荐

  1. MySQL使用二进制日志来恢复数据
  2. windows下安装mysql5.6解压版,32位和64位
  3. Mysql的存储引擎之:MyISAM存储引擎
  4. Mysql基础之 基础知识解释
  5. 如何向mysql数据库添加多个映像?
  6. Sql查询性能限制行数之间的差异
  7. PHP分页算法详解
  8. mysql忘记帐号密码 解决办法。
  9. window 下 mysql 启动 二进制日志文件
  10. 获取项目列表的更好方法:缓存序列化数据与