python中的with与上下文管理器

本文详细介绍了Python中with语句的使用方法及其背后的上下文管理器原理。通过具体实例展示了如何利用with语句简化文件操作及数据库连接管理,提高代码的健壮性和可维护性。

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

           最近看到有 “with” 关键字的语句,它通常用在什么场景呢?我们在操作对于一些文件的打开、数据库连接、socket 等等,应用程序打开这些资源并执行完业务逻辑之后,必须做的一件事就是要关闭(断开)该资源,否则资源将会被占用。本篇将介绍with和上下文管理器的简单应用,还有一个数据库的小应用。

来看看如何正确关闭一个文件。

小白:

def m1 ():
f = open ( " output.txt " , " w " )
f . write ( " python之禅 " )
f . close ()

但是打开文件和文件的读写是有风险的,可能会出现IOError异常,这样会导致文件的f.close()不会被调用,因此资源就得不到释放。

这时就引出了try......finally

入门:

def m2 ():
f = open ( " output.txt " , " w " )
try :
f . write ( " python之禅 " )
except IOError :
print ( " sorry error " )
finally :
f . close ()

使用try来捕捉异常,如果没有读到文件出现异常跳到except中继续执行,不关读没读到文件,最终都会执行finally,关闭文件。

虽然关闭文件得到了解决,但是每次打开文件太过于繁琐,接下来介绍一种方法with

初学:

def m3 ():
with open ( " try.txt " , " r " ) as f :
content = f . read ()

一种更加简洁、优雅的方式就是用 with 关键字。open 方法的返回值赋值给变量 f,当离开 with 代码块的时候,系统会自动调用 f.close() 方法, with 的作用和使用 try/finally 语句是一样的。那么它的实现原理是什么?在讲 with 的原理前要涉及到另外一个概念,就是上下文管理器(Context Manager)

上下文管理器:

任何实现了__enter__ __exit__() 方法的对象都可称之为上下文管理器,上下文管理器对象可以使用 with 关键字。显然,文件(file)对象也实现了上下文管理器。

那么文件对象是如何实现这两个方法的呢?我们可以模拟实现一个自己的文件类,让该类实现 __enter__() 和 __exit__() 方法。

class open_file ():
def __init__ ( self , filename , mode ):
self . filename = filename
self . mode = mode
def __enter__ ( self ):
print ( " enter " )
self . f = open ( self . filename , self . mode )
return self . f
def __exit__ ( self , exc_type , exc_val , exc_tb ):
print ( " will exit " )
self . f . close ()

使用方法:

    with open_file ( " try.txt " , " r " ) as f :
     with_body

运行结果:

enter
will exit
hello world

大致对with语句的执行原理总结Python上下文管理器与with语句:

  • 执行 open_file以获取上下文管理器
  • 加载上下文管理器的 exit() 方法以备稍后调用
  • 调用上下文管理器的 enter() 方法
  • 如果有 as f 从句,则将 enter() 方法的返回值赋给 f
  • 执行子代码块 with_body
  • 调用上下文管理器的 exit() 方法,如果 with_body 的退出是由异常引发的,那么该异常的 type、value 和 traceback 会作为参数传给 exit(),否则传三个 None
  • 如果 with_body 的退出由异常引发,并且 exit() 的返回值等于 False,那么这个异常将被重新引发一次;如果 exit() 的返回值等于 True,那么这个异常就被无视掉,继续执行后面的代码


下面写了一个使用上下文管理器对数据库操作的例子:

from pymysql import *

class DB ( object ):
def __init__ ( self , databasename , password )
# 1、连接数据
# 创建Connection
self . conn = connect ( host = ' localhost ' , port = 3306 , database = str ( databasename ),
                    user
= ' root ' , password = str ( password ), charset = ' utf8 ' )
# 获取Cursor对象
self . csl = self . conn . curser ()
def __enter__ ( self ):
return self . csl;
def __exit__ ( self , exc_type , exc_val , exc_tb ):
self . csl . close ()
self . conn . close ()

with DB ( " jing_dong " , " mysql " ) as db :
db . execute ( " select * from goods_brands; " )
content = db . fetchall ()

print ( content )

总结就不写了。。。。。。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值