您的位置:首页 > 编程语言 > Python开发

Python上下文管理—with语句的用法

2017-05-21 01:12 776 查看
转载请注明出处:http://blog.csdn.net/jinixin/article/details/72590815

在我阅读Python核心编程有关with语句的部分时,我没有弄懂到底讲了什么?with语句能带来什么好处?后来对它的理解逐渐清晰了起来,所以本文便想谈一谈我对with语句现在的理解,本篇文章之后还会再次更新。

我先介绍with的概念,然后谈一下与其相关的两个方法,最后抛出一个例子。可以结合例子回过头来看这些概念,希望对大家有所帮助。

with的用处

我把with语句理解为对try,except和finally的一种封装。使用with语句可以让程序结构看似更简单,避免代码重复,更加pythonic。with语句仅能工作于支持上下文管理协议的对象,即该对象必须实现__enter__与__exit__方法。



with的样子

with 表达式[ as 变量]:
with子语句块


具体例子,如打开文件并打印:

with open('/path/to/file','r') as file:
for line in file:
print line,


上述代码在执行完毕时能自动关闭文件,无论是否有异常;甚至通过修改,我们可以让with自动处理异常。总之,with可以让我们把注意力从惦记着释放资源,处理异常等琐事上更多地转移到如何更好的写代码,使程序更高效。

with语句执行流程

这部分可以结合上面with语句结构来看。

首先,with对其后的表达式进行求值,该表达式会返回一个对象,该对象一定包含__enter__与__exit__两个特殊方法。该对象一旦被返回,会立即自动调用__enter__方法,该方法返回的结果会被赋值给as关键字后的变量。此处注意,with后表达式的结果并没有赋值给变量,是__enter__方法的返回值被赋给了该变量。

with语句表达式的作用是返回一个遵循上下文管理协议的对象,即该对象必须实现__enter__与__exit__方法。

实现上下文管理协议的两个必要方法

__enter__:

1)形式:__enter__(self)

2)该方法主要负责在with子语句块执行前进行一些配置。

3)表达式返回结果对象时,立即调用返回对象的该方法。如果表达式后有as关键字,该方法的返回值被赋值给as后的变量;如果没有as关键字,则该方法的返回值被抛弃。

__exit__:

1)形式:__exit__(self, exc_type, exc_instance, traceback),3个参数分别表示异常类型,异常实例,回溯函数。如果with子句没有发生异常,3个参数全部为None;但一旦发生异常,3个参数便会被填充。

2)该方法在整个with语句块运行完毕后执行,用于释放资源或处理异常等。即使with子语句块内发生了异常,该方法也一定会执行。

3)当with子语句块发生异常时,会立即执行__exit__方法,__exit__方法可以选择是否处理并“包庇”该异常。当__exit__方法返回为True时,Python解释器会继续执行with语句后面的代码(注意,with子语句块内的后面代码不会被执行),返回False时,则抛出该异常。

例子

最后举一个用到的例子,有关于数据库的(MySQLdb是第三方模块,可通过“pip install mysql-python”安装):

#!/usr/bin/env python
# coding=utf-8

import MySQLdb

class SqlTool(object):

def __init__(self, db, user='数据库用户', pwd='数据库密码', host='localhost', port=3306):
self.connect = MySQLdb.connect(user=user, passwd=pwd, host=host, port=port, db=db)  # 创建数据库连接
self.cursor = self.connect.cursor()  # 创建游标

def __enter__(self):
return self.cursor                   # 返回游标给with语句的cursor变量

def __exit__(self, exc_type, exc_instance, traceback):
if exc_instance:
print exc_instance
self.cursor.close()                  # 关闭游标
self.connect.commit()                # 确认提交
self.connect.close()                 # 关闭连接
return True                          # with语句发生的所有异常都不抛出

with SqlTool(db='test') as cursor:
cursor.execute('insert into people(name, age) values (%s, %s)', ('jinixin', 20))


参考自Python核心编程第二版10.4节,Python高级编程第2章

文中如有不恰当的地方,还望包容和指出,感谢
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息