python炫酷母亲节 母亲节python代码_执行过程

使用with自动关闭资源

来做个简单的试验,观察一下发生的现象。在Python解释器中输入下面两行代码,会有什么情况发生呢?

python炫酷母亲节 母亲节python代码_执行过程_02

使用with自动关闭资源

结果是:在解释器所在的目录下生成了一个文件test.txt,并且在里面写入了字符申test,对吗?

事实真相是:的确生成了一个文件,但其内容为空,并没有写入任何字符串。这个一个简单得不能再简单的问题,相信不用多说你已经知道症结所在了。

对文件操作完成后应该立即关闭它们,这是一个常识。我们都知道需要这么做,在很多编程语言中都会强调这个问题。因为打开的文件不仅会占用系统资源,而且可能影响其他 程序或者进程的操作,甚至会导致用户期望与实际操作结果不一致。

但实际应用中真相往往是:即使我们心中记得这个原则,但仍然可能会忘记关闭它。为什么?因为编程人员会把更多的精力和注意力放在对具体文件内容的操作和处理上;或者设计的正常流程是处理完毕关闭文件,但结果程序执行过程中发生了异常导致关闭文件的代码没有被执行到。也许你会说,还有try.finally块。对!

这是一种比较古老的方法,但Python提供了一种更为简单的解决方案:with语句。with语句的语法为:

with表达式[as目标]:

代码块

with语句支持嵌套,支持多个with子句,它们两者可以相互转换。"with exprl as el , expr2 as e2"与下面的嵌套形式等价:

python炫酷母亲节 母亲节python代码_执行过程_03

嵌套形式等价

with语句可以在代码块执行完毕后还原进入该代码块时的现场。包含有with语句的代码块的执行过程如下:

1)计算表达式的值,返回一个上下文管理器对象。

2)加载上下文管理器对象的_exit_()方法以备后用。

3)调用上下文管理器对象的_enter_()方法。

4)如果with语句中设置了目标对象,则将_enter_()方法的返回值赋值给目标对象。

5)执行with中的代码块。

6)如果步骤5中代码正常结束,调用上下文管理器对象的_exit_()方法,其返回值直接忽略。

7)如果步骤5中代码执行过程中发生异常,调用上下文管理器对象的_exit_()方法,并将异常类型、值及traccback信息作为参数传递给_exit_O方法。如果_exit_()返回值为 false,则异常会被重新抛出;如果其返回值为true,异常被挂起,程序继续执行。

在文件处理时使用with的好处在于无论程序以何种方式跳岀with块,总能保证文件被正确关闭。实际上它不仅仅针对文件处理.针对其他情景同样可以实现运行时环境的清理与还原,如多线程编程中的锁对象的管理。

with的神奇实际得益于一个称为上下文管理器 (context manager)的东西,它用来创建一个运行时的环境。上下文管理器是这样一个对象:它定义程序运行时需要建立的上下文,处理程序的进入和退出,实现了上下文管理协议,即在对象中定义_enter_()和_exit_()方法。其中:

1._enter_():进入运行时的上下文,返冋运行时上下文相关的对象,with语句中会将 这个返回值绑定到目标对象。如上面的例子中会将文件对象本身返回并绑定到目标f。

2.exit(exccption_type,exception_value,traceback):退出运行时的上下文,定义在块执行(或终止)之后上下文管理器应该做什么。它可以处理异常、清理现场或者处理with块中语句执行完成之后需要处理的动作。

实际上任何实现了上下文协议的对象都可以成为一个上下文管理器,文件也是实现了这个协议的上下文管理器,它们都能够与with语句兼容。文件对象的_enter_和_exit_属性如下:

python炫酷母亲节 母亲节python代码_执行过程_04

文件对象的_enter_和_exit_属性

用户也可以定义自己的上下文管理器来控制程序的运行,只需要实现上下文协议便能够和with语句一起使用。

python炫酷母亲节 母亲节python代码_代码块_05

上下文管理器来控制程序

因为上下文管理器主要作用于资源共享,因此在实际应用中__enter__和__exit__ 法基本用于资源分配以及释放相关的工作,如打开/关闭文件、异常处理、断开流的连接、锁分配等。

为了更好地辅助上下文管理,Python还提供了contextlib模块,该模块是通过 Generator实现的,contextlib中的contextmanager作为装饰器来提供一种针对函数级别的上下文管理机制,可以直接作用于函数/对象而不用去关心_enter()_和_exit()_方法的具体实现。

马上母亲节了,记得给家里的妈妈一份问候

python炫酷母亲节 母亲节python代码_代码块_06

母亲节