with与“上下文管理器”,以及其在数据库上的应用

本文介绍了Python中with语句的使用方法及其背后的上下文管理器原理。通过具体的文件操作和数据库连接示例,展示了如何利用with语句简化资源管理和释放过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

with与“上下文管理器”

    相信很多人在阅读别人代码的时候,会看到用with打开文件的方式,如:


with open("code.py","w") as file:

    file.write("Life's short! Use python.")

    那么这种打开方式有什么好处呢?

    对于文件而言,如果需要频繁地操作的话,没完没了的关闭确实不胜其烦,有的时候比如 Python 程序打开一个文件,往文件中写内容,写完之后,就要关闭该文件,否则会出现什么情况呢?极端情况下会出现 "Too many open files" 的错误,因为系统允许你打开的最大文件数量是有限的。同样,对于数据库,如果连接数过多而没有及时关闭的话,就可能会出现 "Can not connect to MySQL server Too many connections",因为数据库连接是一种非常昂贵的资源,不可能无限制的被创建。于是乎,一种新的打开文件的方式诞生了——也就是with。

    with的好处显而易见,就是在打开文件,并且操作之后,python程序会自动地为你关闭这个文件,而不再需要手动地去关闭,这就防止了同时有很多文件打开的情况,也就避免了一些不必要的错误。那么,既然with这么好用,那它的底层原理到底是什么呢?我们可不可以用with来进行其他的类似数据库,socket连接等的响应操作呢?

    with的底层原理是使用了上下文管理器:

    任何实现了 __enter__() 和 __exit__() 方法的对象都可称之为上下文管理器,上下文管理器对象可以使用 with 关键字。显然,文件(file)对象也实现了上下文管理器。__enter__() 和 __exit__() 方法都是属于魔法方法,相信大家对魔法方法都已经耳熟能详了。通俗来说,就是在特定的情况下,魔法方法会自动执行。在这里,__enter__() 方法会在打开文件的时候执行,并且返回资源对象,这里就是你将要打开的那个文件对象,__exit__() 方法则会在操作完文件之后执行,这里会处理一些清除工作那么文件对象是如何实现这两个方法的呢?我们可以模拟实现一个自己的文件类,让该类实现 __enter__() 和 __exit__() 方法。



class File(object):
    def __init__(self,file_name,open_mode):
        self.file = open(str(file_name),str(open_mode))      # 打开文件


    def __enter__(self):
        return self.file        # 返回文件对象


    def __exit__(self, exc_type, exc_val, exc_tb):
        self.file.close()       # 关闭文件




with File('code.py','w') as file:
    print("-------writing-------")
    file.write("life's short! Use python.")

在这里,我们可以看到with打开文件的原理代码,那么接下来给大家展示一下操作数据库的代码,当然,前提是你要准备好一个数据库(不重要的!)



from pymysql import *




class Database(object):
    def __init__(self,name,password):
        # 创建self.conn连接
        self.conn = connect(host='localhost',port=3306,database=str(name),user='root',password=str(password),charset='utf8')
        # 获得self.cursor对象
        self.cursor = self.conn.cursor()


    def __enter__(self):
        return self.cursor      # 返回self.cursor对象


    def __exit__(self, exc_type, exc_val, exc_tb):
        self.cursor.close()     # 关闭self.cursor对象
        self.conn.close()       # 关闭self.conn连接




with Database('zzj_01','mysql') as db:
    db.execute(""" select * from students; """)     # 执行sql语句
    content = db.fetchall()                         # 获取数据
# 遍历获取到的数据,打印每一条数据
for info in content:
    print(info)

相信大家看到这里已经对with的用法已经很了解了,其实socket的with用法也差不多,大家可以自己动手敲一敲,自己好好体会一下。今天就到这里了,谢谢大家!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值