最近看到有 “with” 关键字的语句,它通常用在什么场景呢?我们在操作对于一些文件的打开、数据库连接、socket 等等,应用程序打开这些资源并执行完业务逻辑之后,必须做的一件事就是要关闭(断开)该资源,否则资源将会被占用。本篇将介绍with和上下文管理器的简单应用,还有一个数据库的小应用。
来看看如何正确关闭一个文件。
小白:
但是打开文件和文件的读写是有风险的,可能会出现IOError异常,这样会导致文件的f.close()不会被调用,因此资源就得不到释放。
这时就引出了try......finally。
入门:
使用try来捕捉异常,如果没有读到文件出现异常跳到except中继续执行,不关读没读到文件,最终都会执行finally,关闭文件。
虽然关闭文件得到了解决,但是每次打开文件太过于繁琐,接下来介绍一种方法with。
初学:
一种更加简洁、优雅的方式就是用 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 = filenameself . mode = modedef __enter__ ( self ):print ( " enter " )self . f = open ( self . filename , self . mode )return self . fdef __exit__ ( self , exc_type , exc_val , exc_tb ):print ( " will exit " )self . f . close ()
使用方法:
运行结果:
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,那么这个异常就被无视掉,继续执行后面的代码
下面写了一个使用上下文管理器对数据库操作的例子:
user = ' root ' , password = str ( password ), charset = ' utf8 ' )
总结就不写了。。。。。。。。。