Python的with上下文管理

引言

使用 with 语句和上下文管理器是 Python 中管理资源的优雅方式。上下文管理器确保在代码块执行前和执行后执行一些操作,常用于管理文件、数据库连接、线程锁等资源。

什么是with语句和上下文管理器

with 语句用于简化资源管理,它会在代码块执行前调用上下文管理器的 __enter__ 方法,并在代码块执行后调用 __exit__ 方法。上下文管理器确保无论是否发生异常,资源都会被正确释放。
基本语法如下:

with open('text.log','r',encoding='utf-8') as file:
        for line in file:
            print(line.strip())

使用with管理文件操作

文件操作是with语句最常见的应用场景之一,使用with语句可以确保文件在使用完毕后自动关闭,不需要收到您调用文件关闭函数,即时在操作过程中发生异常。
代码示例可参照上面的代码
open函数返回一个文件对象,with语句调用文件对象的__enter__方法打开文件,并在代码块结束后调用__exit__方法关闭文件。

编写自定义上下文管理器

我们可以使用__enter____exit__方法实现一个自定义的上下文管理器,下面示例实现一个简单的文件管理器

class FileManager:
    
    def __init__(self,filename,mode):
        self.filename = filename
        self.mode = mode
        self.file = None
        
    def is_closed(self):
        if self.file:
            return self.file.closed
        
    def __enter__(self):
        self.file = open(self.filename,self.mode,encoding='utf-8')
        return self.file
    
    def __exit__(self,exc_type,exc_value,traceback):
        if self.file:
            self.file.close()
            
        # 处理异常(可选)
        if exc_type:
            print(f"Exception type: {exc_type}")
            print(f"Exception value: {exc_value}")
            print(f"Traceback: {traceback}")
        # 返回 True 表示异常已处理,不再传播;返回 False 表示异常未处理,继续传播
        return False
 
 if __name__ == '__main__':
    with FileManager('text.txt', 'a') as file:
        for i in range(10):
            file.write(f'{i}\n')

使用@contextmanager装饰器

Python提供了contextlib.contextmanager 装饰器允许你使用生成器函数编写上下文管理器,简化了定义过程。生成器函数的 yield 语句分隔了 enterexit 方法的代码。

from contextlib import contextmanager

@contextmanager
def file_manager(filename,mode):
    file = open(filename,mode,encoding='utf-8')
    try:
    	yield file
    finally:
    	file.close()
    
with file_manager('乐都节水.txt', 'a') as file:
        for i in range(10):
            file.write(f'{i}\n')

在这个示例中,加入了yield关键字,在yield之前,相当于__enter__,yield之后相当于__exit__,使用contextmanager装饰器,实现with上下文管理器更为简单

上下文管理器的实际应用

除了文件操作和性能测量,上下文管理器还有许多实际应用,例如:

  • 数据库连接:确保数据库连接在使用后关闭。
  • 线程锁:确保线程锁在使用后释放。
  • 临时文件:确保临时文件在使用后删除。
    下面展示一个数据库连接示例,在我们使用sqlite3时,如果连接没有即时释放,很容易造成后面的操作无法执行的问题,
from contextlib import contextmanager
import sqlite3

@contextmanager
def database_connection(db_name):
    conn = sqlite3.connect(db_name)
    try:
        yield conn
    finally:
        conn.close()
        
# 使用 @contextmanager 装饰器管理数据库连接
with database_connection('data.db') as conn:
    cursor = conn.cursor()
    cursor.execute('SELECT * FROM RealData')
    for row in cursor.fetchall():
        print(row)

上面代码中,database_connection 生成器方式在yield前打开数据库连接,并在之后关闭连接,确保数据库连接在使用后自动释放

结论

使用 with 语句和上下文管理器可以大大简化资源管理,确保资源在使用后自动释放,减少错误和资源泄漏的风险。通过编写自定义上下文管理器或使用 @contextmanager 装饰器,你可以将常见的资源管理任务封装起来,使代码更加简洁和易于维护。

上下文管理器不仅限于文件操作和数据库连接,还可以应用于各种需要在使用后进行清理的资源管理任务。理解和使用上下文管理器是提升 Python 编程技能的重要一步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值