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

news2024/9/9 4:17:01

文末赠免费精品编程资料~~

今天,我们要探索的是Python中一个超级实用又往往被低估的特性——上下文管理器。这可不是普通的魔法,它能让你的代码更加整洁、安全,还能自动处理资源,就像变魔术一样。准备好,让我们一起揭开它的神秘面纱。

1. 自动打开和关闭文件

问题场景:每次操作文件,都要手动打开和关闭,忘了close()可是大忌。

优雅解决方案

with open('example.txt', 'r') as file:
    content = file.read()

这段代码自动管理了文件句柄,无论是否发生异常,文件都会被正确关闭。魔法在于with关键字,后面跟着的就是上下文管理器对象。

2. 自定义上下文管理器

进阶玩法:自己定义上下文管理器,比如计时器。

class Timer:
    def __enter__(self):
        self.start = time.time()

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.end = time.time()
        print(f"操作耗时: {self.end - self.start}秒")

with Timer():
    time.sleep(2)

这里,__enter____exit__是关键方法,让类变成了上下文管理器。

3. 使用contextlib简化代码

简化秘诀:不想写类?contextlib.contextmanager来帮忙。

from contextlib import contextmanager

@contextmanager
def simple_timer():
    start = time.time()
    yield
    end = time.time()
    print(f"耗时: {end - start}秒")

with simple_timer():
    time.sleep(1)

yield像一个分界点,之前的是__enter__,之后的是__exit__

4. 数据库连接管理

实战案例:数据库操作中,自动管理连接和关闭。

from contextlib import closing
import sqlite3

with sqlite3.connect("my_database.db") as connection:
    with closing(connection.cursor()) as cursor:
        cursor.execute("SELECT * FROM users")
        print(cursor.fetchall())

这里,closing也是一个上下文管理器,确保连接在操作完成后关闭。

5. 锁定资源避免并发冲突

并发安全:在多线程环境下,使用threading.Lock作为上下文管理器。

import threading

lock = threading.Lock()

with lock:
    # 在这里进行需要保护的代码
    print("我是安全的并发操作")

确保同一时间只有一个线程访问这段代码。

6. 自动重试机制

提升稳定性:利用上下文管理器实现自动重试逻辑。

from retrying import retry

@retry(stop_max_attempt_number=3)
def unreliable_function():
    if not random.randint(0, 1):
        raise Exception("Failed!")
    else:
        print("成功执行了!")

unreliable_function()

虽然不是直接的上下文管理器示例,但通过装饰器实现了类似的效果。

7. 临时改变配置或环境变量

环境控制:在特定范围内临时修改配置。

class TempConfig:
    def __init__(self, key, value):
        self.key, self.old_value = key, os.environ.get(key)

    def __enter__(self):
        os.environ[self.key] = self.value

    def __exit__(self, *args):
        if self.old_value is None:
            del os.environ[self.key]
        else:
            os.environ[self.key] = self.old_value

with TempConfig('DEBUG', 'True'):
    print(os.environ['DEBUG'])  # 输出: True
print(os.environ.get('DEBUG'))  # 如果之前没设置,这里可能输出None

8. 自动清理临时文件

资源管理:生成并自动清理临时文件。

import tempfile

with tempfile.TemporaryFile() as temp_file:
    temp_file.write(b"Hello, World!")
    temp_file.seek(0)
    print(temp_file.read().decode())
# 文件自动删除,无需显式调用temp_file.close()

临时文件在离开with块后自动消失。

9. 日志上下文管理

日志管理:根据不同的上下文调整日志级别。

class LogLevelManager:
    def __init__(self, logger, level):
        self.logger = logger
        self.prev_level = logger.getEffectiveLevel()

    def __enter__(self):
        self.logger.setLevel(level)

    def __exit__(self, *args):
        self.logger.setLevel(self.prev_level)

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

with LogLevelManager(logger, logging.DEBUG):
    logger.debug("这是调试信息")

这样可以在特定代码段内调整日志级别,而不影响全局设置。

10. 错误处理与回滚

事务管理:在数据库操作中,确保要么全成功,要么全失败。

# 假设有一个数据库事务处理函数
def transaction_operation(db_connection):
    try:
        # 执行一系列数据库操作
        db_connection.commit()
    except Exception as e:
        db_connection.rollback()
        raise e

# 使用上下文管理器包装事务逻辑
with db_connection:
    transaction_operation(db_connection)

这里假设db_connection是一个支持上下文管理的数据库连接对象,自动处理提交和回滚。


高级用法和最佳实践

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

高级技巧:有时候,我们需要同时管理多个资源,这时可以链式使用多个上下文管理器。

with open('file.txt', 'w') as file, sqlite3.connect('database.db') as connection:
    file.write("准备存储数据...")
    cursor = connection.cursor()
    cursor.execute("INSERT INTO table VALUES (?)", ('data',))

这段代码展示了如何同时管理文件和数据库连接,确保两个资源都被妥善处理。

12. 上下文表达式

简洁编码:Python 3.7+引入了上下文表达式,使得单行上下文管理变得可能。

content = (open('example.txt', 'r').read())

虽然这种方式简洁,但在处理可能抛出异常的情况时不如with语句清晰,不推荐用于复杂的资源管理。

13. 上下文管理器的替代方案 - 使用finally

了解替代方案:在没有上下文管理器的情况下,try...finally...是确保资源清理的经典方式。

file = open('file.txt', 'w')
try:
    file.write("Hello, World!")
finally:
    file.close()

但这不如上下文管理器优雅,且容易忘记。

14. 第三方库中的上下文管理器

扩展知识:许多第三方库提供了自己的上下文管理器,如requests库中的响应对象自动关闭。

import requests

with requests.get('https://api.example.com/data') as response:
    data = response.json()

这里,response对象在退出with块时自动关闭连接。

15. 设计模式与上下文管理器

设计思维:将上下文管理器应用于设计模式,如单例模式,确保资源的唯一实例。

class SingletonMeta(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            instance = super().__call__(*args, **kwargs)
            cls._instances[cls] = instance
        return cls._instances[cls]

class Singleton(metaclass=SingletonMeta):
    pass

# 使用时
singleton1 = Singleton()
singleton2 = Singleton()
assert singleton1 is singleton2

虽然这个例子没有直接使用上下文管理器,但它展示了元类如何在更深层次上控制对象的创建,这与上下文管理器在资源控制上的理念相呼应。

结语

通过这些深入的探讨,你不仅掌握了上下文管理器的基础和高级用法,还学会了如何将其融入更广泛的设计思想中。

好了,今天的分享就到这里了,我们下期见。如果本文对你有帮助,请点赞、转发、点个在看吧!

文末福利

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1961050.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一分多行列转换(Gbase版)

1、源数据表结构 CREATE TABLE "sf_ref_pd_config" ("I_BATCH_NO" decimal(5,0) DEFAULT NULL COMMENT 批次ID,"V_ASSET_CLASS_NAME" varchar(200) DEFAULT NULL COMMENT 资产类型,"N_EXEC_ID" decimal(5,0) DEFAULT NULL COMMENT 执…

pyjwt:Python 中的 JWT 处理专家

文章目录 探索 pyjwt:Python 中的 JWT 处理专家简介:为何选择 pyjwt?什么是 pyjwt?安装 pyjwtpyjwt 的基本使用1. 编码JWT2. 解码JWT3. 验证签名4. 过期时间5. 自定义头部 场景应用场景一:用户登录场景二:A…

深度学习的数据类型总结

文章目录 1.基本概念1.比特(bit):2. **字节**(Byte):2. **数据类型**: 2. 相互转化 1.基本概念 1.比特(bit): 计算机中最小的数据存储单位,用 0 和 1 表示。信息传输速…

python制作一个AI聊天机器人-【python教程】教你用python制作一个AI聊天机器人,源码可分享,零基础也能实现!

要制作一个基本的AI聊天机器人,我们可以使用Python的多个库,其中一个非常流行且易于上手的是Rasa。一个简单的入门示例,我们可以使用pyttsx3,是一个Python库,用于将文本转换为语音。 它提供了一个简单易用的接口&#…

【ThingsBoard初体验】本地运行源码踩坑记录

前言 运行源码之前,请先编译源码。这很重要!!! 官网源码编译教程:http://www.ithingsboard.com/docs/user-guide/contribution/yuanmabianyi/ 如果编译过程中出现报错,请看我上一篇文章:【Thing…

《LeetCode热题100》---<滑动窗口篇两道>

本篇博客讲解LeetCode热题100道滑动窗口篇中的两道题 第一道:无重复字符的最长子串 第二道:找到字符当中的所有字母异位词 第一道:无重复字符的最长子串 哈希滑动窗口 class Solution {public int lengthOfLongestSubstring(String s0) {int…

nginx出现Refused to apply inline style because it violates

Content Security Policy的错误。根据错误提示,nginx拒绝应用内联样式,因为它违反了内容安全策略(Content Security Policy)。内容安全策略是一种浏览器机制,用于防止潜在的安全漏洞,通过限制从外部来源加载…

初步入门C ++之继承的概念

继承 ​ 继承,他的功能就如同他的名字一样,可以继承一个类的数据和方法,然后增添一些自己独有的数据和方法: 根据我们之前讲解初步入门C之类的例子,假如我们现在有一个长方体的类,它和长方型类唯一不一样…

屏幕录制与视频编辑的新纪元Camtasia Studio 2024

在数字化时代,视频已成为我们日常工作和生活中不可或缺的一部分。无论是教育、培训、营销还是娱乐,高质量的视频内容都发挥着至关重要的作用。而提到屏幕录制和视频编辑软件,Camtasia Studio无疑是一个家喻户晓的名字。随着2024年新版本的发布…

【Vue3】自定义组件

【Vue3】自定义组件 背景简介开发环境开发步骤及源码 背景 随着年龄的增长,很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来,技术出身的人总是很难放下一些执念,遂将这些知识整理成文,以纪念曾经努力学习奋斗的日子。本文…

Java基本语法学习的案例练习

本文是在学习过C语言后,开始进行Java学习时,对于基本语法的一些案例练习。案例内容来自B站黑马编程课 1.HelloWorld 问题介绍;请编写程序输出“HelloWorld”. public class HelloWorld { public static void main(String[] args) { System.out.print…

树状机器学习模型综述(含python代码)

树状机器学习模型综述 树状模型是机器学习中一种非常重要的算法类别,因其直观的结构和良好的可解释性而广泛应用于分类和回归任务。本文将综述几种常见的树状模型,包括决策树、随机森林、LightGBM、XGBoost和CatBoost,讨论它们的原理、用途以…

高品质定制线缆知名智造品牌推荐-精工电联:高压线缆行业定制服务的领航者

定制线缆源头厂家推荐-精工电联:高压线缆行业定制服务的领航者 在当今这个高度信息化的社会,电力传输与分配系统的稳定运行至关重要。作为连接各个电力设备的纽带,高压线缆的质量直接关系到电力系统的安全性和稳定性。在定制高压线缆行业中&a…

【RK3568】点亮eDP屏幕+双屏异显

一、驱动eDP屏幕 一般来说,屏幕的规格书中会找到屏幕的相关参数,如没有,也可直接找屏幕厂商要,首先打开屏幕的规格书,搜索EDID Table,可找到如下信息: (1)显示时序配置 将…

越是熟人之间,越要注意这三个方面

不管什么时候,不管与谁相处,社交的边界和底线永远都是不变的。 对待陌生人的时候,我们总会按照既定的章法和礼节行事,可是在对待熟人的时候,很多人却忘了这些章法和礼节。虽然彼此熟悉了,不需要那么在乎章…

狗都能看懂的Imitation Learning的讲解

上一篇博客讲述了奖励稀疏时的训练方法。实际场景中,可能难度还会更大一些。很多场景很难有一个明确的reward,甚至没有reward。那么这里就提出模仿学习,即agent模仿expert的操作。具体两个方法是:Behavior Cloning、Inverse Reinf…

从0到100:旅拍小程序开发笔记(上)

背景调研 旅拍店或者摄影师可以在小程序上设置自己的可预约时间,价格,拍摄介绍,并定义不同的套餐(服装套数,底片张数,精修数量,取景风格,套餐价格等),顾客可以根据套餐内容和日程安…

定制化Windows系统

定制化Windows系统 1、定制化需求介绍 预定义安装常用软件的原版操作系统,节省花费的时间。定制前提,你需要1块硬盘、1台(2台)测试电脑、一个PE盘(wepe最好),原版系统镜像,虚拟光驱…