Python中15个让你代码更优雅的上下文管理器用法

打印 上一主题 下一主题

主题 887|帖子 887|积分 2661


文末赠免费佳构编程资料~~
本日,我们要探索的是Python中一个超级实用又每每被低估的特性——上下文管理器。这可不是普通的魔法,它能让你的代码更加整齐、安全,还能自动处理资源,就像变把戏一样。准备好,让我们一起揭开它的神秘面纱。
1. 自动打开和关闭文件

题目场景:每次操纵文件,都要手动打开和关闭,忘了close()可是大忌。
优雅解决方案
  1. with open('example.txt', 'r') as file:
  2.     content = file.read()
复制代码
这段代码自动管理了文件句柄,无论是否发生非常,文件都会被正确关闭。魔法在于with关键字,后面跟着的就是上下文管理器对象。
2. 自定义上下文管理器

进阶玩法:自己定义上下文管理器,好比计时器。
  1. class Timer:
  2.     def __enter__(self):
  3.         self.start = time.time()
  4.     def __exit__(self, exc_type, exc_val, exc_tb):
  5.         self.end = time.time()
  6.         print(f"操作耗时: {self.end - self.start}秒")
  7. with Timer():
  8.     time.sleep(2)
复制代码
这里,__enter__和__exit__是关键方法,让类变成了上下文管理器。
3. 使用contextlib简化代码

简化法门:不想写类?contextlib.contextmanager来帮助。
  1. from contextlib import contextmanager
  2. @contextmanager
  3. def simple_timer():
  4.     start = time.time()
  5.     yield
  6.     end = time.time()
  7.     print(f"耗时: {end - start}秒")
  8. with simple_timer():
  9.     time.sleep(1)
复制代码
yield像一个分界点,之前的是__enter__,之后的是__exit__。
4. 数据库毗连管理

实战案例:数据库操纵中,自动管理毗连和关闭。
  1. from contextlib import closing
  2. import sqlite3
  3. with sqlite3.connect("my_database.db") as connection:
  4.     with closing(connection.cursor()) as cursor:
  5.         cursor.execute("SELECT * FROM users")
  6.         print(cursor.fetchall())
复制代码
这里,closing也是一个上下文管理器,确保毗连在操纵完成后关闭。
5. 锁定资源制止并发冲突

并发安全:在多线程环境下,使用threading.Lock作为上下文管理器。
  1. import threading
  2. lock = threading.Lock()
  3. with lock:
  4.     # 在这里进行需要保护的代码
  5.     print("我是安全的并发操作")
复制代码
确保同一时间只有一个线程访问这段代码。
6. 自动重试机制

提升稳定性:使用上下文管理器实现自动重试逻辑。
  1. from retrying import retry
  2. @retry(stop_max_attempt_number=3)
  3. def unreliable_function():
  4.     if not random.randint(0, 1):
  5.         raise Exception("Failed!")
  6.     else:
  7.         print("成功执行了!")
  8. unreliable_function()
复制代码
固然不是直接的上下文管理器示例,但通过装饰器实现了雷同的结果。
7. 临时改变配置或环境变量

环境控制:在特定范围内临时修改配置。
  1. class TempConfig:
  2.     def __init__(self, key, value):
  3.         self.key, self.old_value = key, os.environ.get(key)
  4.     def __enter__(self):
  5.         os.environ[self.key] = self.value
  6.     def __exit__(self, *args):
  7.         if self.old_value is None:
  8.             del os.environ[self.key]
  9.         else:
  10.             os.environ[self.key] = self.old_value
  11. with TempConfig('DEBUG', 'True'):
  12.     print(os.environ['DEBUG'])  # 输出: True
  13. print(os.environ.get('DEBUG'))  # 如果之前没设置,这里可能输出None
复制代码
8. 自动整理临时文件

资源管理:生成并自动整理临时文件。
  1. import tempfile
  2. with tempfile.TemporaryFile() as temp_file:
  3.     temp_file.write(b"Hello, World!")
  4.     temp_file.seek(0)
  5.     print(temp_file.read().decode())
  6. # 文件自动删除,无需显式调用temp_file.close()
复制代码
临时文件在离开with块后自动消失。
9. 日志上下文管理

日志管理:根据差别的上下文调解日志级别。
  1. class LogLevelManager:
  2.     def __init__(self, logger, level):
  3.         self.logger = logger
  4.         self.prev_level = logger.getEffectiveLevel()
  5.     def __enter__(self):
  6.         self.logger.setLevel(level)
  7.     def __exit__(self, *args):
  8.         self.logger.setLevel(self.prev_level)
  9. logger = logging.getLogger(__name__)
  10. logger.setLevel(logging.INFO)
  11. with LogLevelManager(logger, logging.DEBUG):
  12.     logger.debug("这是调试信息")
复制代码
如许可以在特定代码段内调解日志级别,而不影响全局设置。
10. 错误处理与回滚

事件管理:在数据库操纵中,确保要么全成功,要么全失败。
  1. # 假设有一个数据库事务处理函数
  2. def transaction_operation(db_connection):
  3.     try:
  4.         # 执行一系列数据库操作
  5.         db_connection.commit()
  6.     except Exception as e:
  7.         db_connection.rollback()
  8.         raise e
  9. # 使用上下文管理器包装事务逻辑
  10. with db_connection:
  11.     transaction_operation(db_connection)
复制代码
这里假设db_connection是一个支持上下文管理的数据库毗连对象,自动处理提交和回滚。

高级用法和最佳实践

11. 上下文管理器的链式使用

高级本领:有时间,我们需要同时管理多个资源,这时可以链式使用多个上下文管理器。
  1. with open('file.txt', 'w') as file, sqlite3.connect('database.db') as connection:
  2.     file.write("准备存储数据...")
  3.     cursor = connection.cursor()
  4.     cursor.execute("INSERT INTO table VALUES (?)", ('data',))
复制代码
这段代码展示了如何同时管理文件和数据库毗连,确保两个资源都被妥善处理。
12. 上下文表达式

简洁编码:Python 3.7+引入了上下文表达式,使得单行上下文管理变得可能。
  1. content = (open('example.txt', 'r').read())
复制代码
固然这种方式简洁,但在处理可能抛出非常的情况时不如with语句清晰,不推荐用于复杂的资源管理。
13. 上下文管理器的替换方案 - 使用finally

了解替换方案:在没有上下文管理器的情况下,try...finally...是确保资源整理的经典方式。
  1. file = open('file.txt', 'w')
  2. try:
  3.     file.write("Hello, World!")
  4. finally:
  5.     file.close()
复制代码
但这不如上下文管理器优雅,且轻易忘记。
14. 第三方库中的上下文管理器

扩展知识:许多第三方库提供了自己的上下文管理器,如requests库中的相应对象自动关闭。
  1. import requests
  2. with requests.get('https://api.example.com/data') as response:
  3.     data = response.json()
复制代码
这里,response对象在退出with块时自动关闭毗连。
15. 设计模式与上下文管理器

设计头脑:将上下文管理器应用于设计模式,如单例模式,确保资源的唯一实例。
  1. class SingletonMeta(type):
  2.     _instances = {}
  3.     def __call__(cls, *args, **kwargs):
  4.         if cls not in cls._instances:
  5.             instance = super().__call__(*args, **kwargs)
  6.             cls._instances[cls] = instance
  7.         return cls._instances[cls]
  8. class Singleton(metaclass=SingletonMeta):
  9.     pass
  10. # 使用时
  11. singleton1 = Singleton()
  12. singleton2 = Singleton()
  13. assert singleton1 is singleton2
复制代码
固然这个例子没有直接使用上下文管理器,但它展示了元类如何在更深条理上控制对象的创建,这与上下文管理器在资源控制上的理念相呼应。
结语

通过这些深入的探讨,你不但掌握了上下文管理器的底子和高级用法,还学会了如何将其融入更广泛的设计思想中。
好了,本日的分享就到这里了,我们下期见。如果本文对你有帮助,请点赞、转发、点个在看吧!
文末福利

请关注下方公众号并背景回复编程资料免费获取Python编程、人工智能、爬虫等100+本佳构电子书。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

滴水恩情

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表