python 上下文管理器详解

心已赠人 2023-07-14 05:41 62阅读 0赞

python的上下文管理器看了很多解释

vamei的python教程:

上下文管理器(context manager)是Python2.5开始支持的一种语法,用于规定某个对象的使用范围。一旦进入或者离开该使用范围,会有特殊操作被调用 (比如为对象分配或者释放内存)。它的语法形式是with…as…

python编程时光:

  1. 上下文表达式:with open(‘test.txt’) as f:

  2. 上下文管理器:open(‘test.txt’)

  3. f 不是上下文管理器,应该是资源对象。

个人理解是对资源的一些操作!

上下文管理器的实现有两种方式,我用1/0这个例子来展示一下

第一种方式:

  1. """
  2. 一个类实现了 __enter__和__exit__的方法,这个类的实例就是一个上下文管理器
  3. """
  4. import traceback
  5. class Resource():
  6. def __enter__(self):
  7. """
  8. 我们可以将一些资源初始化动作放在 __enter__
  9. 比如:数据库连接,打开文件
  10. 一般返回资源对象
  11. """
  12. print('=== __enter__ ===')
  13. return self
  14. def __exit__(self, exc_type, exc_val, exc_tb):
  15. """
  16. __exit__ 包含三个参数:
  17. exc_type 异常类型
  18. exc_val 异常值
  19. exc_tb 异常的错误栈信息
  20. 当没有异常时三个都是None
  21. __exit__ 包含了异常捕捉和结束动作
  22. """
  23. print(exc_type, exc_val, traceback.print_tb(exc_tb))
  24. print('==== __exit__ ====')
  25. return True
  26. def zero_func(self, x):
  27. print(1/x)
  28. with Resource() as res:
  29. """
  30. as 会把 __enter__ 返回值赋给 目标 res
  31. 如果我们让 __enter__ return 1,在这里我们print(res),会发现res的值是1,
  32. 如果我们在这里print(res),会发现先执行 __enter__ 再 执行__exit__
  33. """
  34. res.zero_func(0)
  35. """
  36. 1/0 原本是会报错的,
  37. 但是这里如果没有在 __exit__ 打印错误信息的话,这里是不会有异常信息的
  38. """

第二种方式:

  1. """
  2. 通过contextlib 创建上下文管理器
  3. """
  4. import traceback
  5. import contextlib
  6. # 使用修饰器 @contextlib.contextmanager
  7. @contextlib.contextmanager
  8. def zero_func(x):
  9. # yield 之前的 都相当于 __enter__ 的内容
  10. print('====== __enter__ =========')
  11. try:
  12. """
  13. yield 后面可以返回一个对象,相当于 __enter__ 的return
  14. """
  15. yield
  16. """
  17. yield 后面的内容相当于__exit__
  18. """
  19. zero_parameter = 1/x
  20. except Exception as exc:
  21. # 处理异常
  22. """
  23. 如果使用traceback.print_exc()会返回一个空对象
  24. 错误信息的打印有可能出现在__exit__之后
  25. """
  26. print(traceback.format_exc())
  27. else:
  28. # 没异常执行部分
  29. print(zero_parameter)
  30. finally:
  31. # 结束
  32. print('===== 结束 ====')
  33. with zero_func(0) as x:
  34. """
  35. 这里print(x)会发现打印出一个None,这个其实是yield返回的空对象
  36. 这里还能看出来,print(x) 虽然在后面但是执行的时候是先执行
  37. """
  38. print(x)

实战用两种上下文管理器实现打开文件:

第一种:

  1. import traceback
  2. class OpenFiles():
  3. def __init__(self, filename, openway):
  4. print('==== __init__ ====')
  5. self.filename = filename
  6. self.openway = openway
  7. self.file_obj = None
  8. def __enter__(self):
  9. print('==== __enter__ ====')
  10. self.file_obj = open(self.filename, self.openway)
  11. return self.file_obj
  12. def __exit__(self, exc_type, exc_val, exc_tb):
  13. print(exc_type, exc_val, traceback.print_tb(exc_tb))
  14. if self.file_obj:
  15. self.file_obj.close()
  16. print('==== __exit__ ====')
  17. return True
  18. with OpenFiles('text.txt', 'r') as res:
  19. """
  20. 如果test.txt不存在会报错,你可以用w创建一个,然后打开往里面写点东西,在改为r
  21. python 中如果文件不存在,r r+会报错,w w+ a a+ 会创建
  22. """
  23. print(res.readlines())

第二种:

  1. import traceback
  2. import contextlib
  3. @contextlib.contextmanager
  4. def open_file(filename, openway):
  5. print('====== __enter__ =========')
  6. try:
  7. file_obj = open(filename, openway)
  8. yield file_obj
  9. print('====== __exit__ =========')
  10. except Exception as exc:
  11. print(traceback.format_exc())
  12. else:
  13. pass
  14. finally:
  15. file_obj.close()
  16. with open_file('text.txt', 'r') as res:
  17. print(res.readlines())

发表评论

表情:
评论列表 (有 0 条评论,62人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Python上下文管理

    1. 上下文管理器 一个类只要实现了 `__enter__()` 和 `__exit__()` 这个两个方法,通过该类创建的对象我们就称之为上下文管理器。 上下文管理器

    相关 python上下文管理

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

    相关 Python深入 上下文管理

    上下文管理器(context manager)是Python2.5开始支持的一种语法,用于规定某个对象的使用范围。一旦进入或者离开该使用范围,会有特殊操作被调用 (比如为对象分