Python中的with和context

本文中所有代码均运行在Python 2.7上

相信大多数的新手都曾经犯过这样的错误:在往文件里进行读/写操作的时候,在操作结束之后忘记关闭文件,而导致没有书写结果,就类似下面的代码:

>>> f = open('demo.txt', 'w')
>>> f.write('test')

而正确的写法应该是下面这样:

>>> f = open('demo.txt', 'w')
>>> f.write('test')
>>> f.close()

在对文件操作完之后,应该及时关闭文件。这样做一是为了文件的数据完全,二是节省系统资源,三是防止可能引起的死锁

第二种写法似乎可以满足我们的要求:在完成文件书写之后,立即关闭了文件。
但问题仍然存在:由于某些程序异常(比如说在写操作的时候磁盘已满)而没有执行关闭文件的操作。那么,有没有方法可以保证文件一定被关闭呢?有些人可能会提出使用try...finally来处理异常出现时的文件关闭。这种方法是可行的,但不是优雅的。真正被官方推荐的方法是使用with语句进行操作:

>>> with open('demo.txt', 'w') as f:
>>>     f.write('text')

这样是不是简洁多了?

接下来就来看看with...as...语句的执行过程。

  1. 计算表达式的值,返回一个上下文管理对象,并把它赋给句柄;
  2. 分别加载上下文管理器的__enter____exit__方法以备调用;
  3. 调用上下文管理器的__enter__方法;
  4. 执行with下的语句块;
  5. 如果上个步骤正常执行完,则执行__exit__;
  6. 如果步骤4执行出现异常,则将异常信息传递给__exit__,如果__exit__执行结果是false则异常继续向上抛出,否则继续执行程序;

以上的执行机制保证在正常和异常发生的情况下,文件都能被正确的关闭。我们也了解了上下文管理器的概念:通过__enter____exit__来定义程序运行的环境,处理程序的进入和退出问题。

  • __enter__():进入运行时的上下文环境,with中将它的返回值(也就是一个上下文对象)绑定到句柄上(上文中是f);
  • __exit__(exc_type, exc_value, traceback):退出运行时的处理方法,可以用于异常处理,现场清理工作;

接下来,我们来自己写一个上下文管理器来作为本文的结尾:

class dbHelper(object):
    import config
    import time
    def __enter__(self):
        db.connect(config.db_addr)
        print 'db connect at '+str(time.time())
    def __exit__(self, exc_type, exc_value, traceback):
        db.shutdown()
        if not exc_type:
            return False
        else:
            logger.error(exc_type, exc_value, traceback)
            return True
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 转载自:http://mp.weixin.qq.com/s/LO1yyFeUA6pR_YPyfDoSig 姓名:梅...
    虐先森阅读 1,448评论 0 1
  • 本文转自浅谈Python的with语句 引言 with 语句是从 Python 2.5 开始引入的一种与异常处理相...
    Syfun阅读 4,025评论 0 50
  • contextlib — Context Manager Utilities contextlib - 上下文管理...
    英武阅读 2,854评论 0 52
  • 术语 要使用 with 语句,首先要明白上下文管理器这一概念。有了上下文管理器,with 语句才能工作。下面是一组...
    lmem阅读 307评论 0 0
  • 今天晚上要去爬泰山,在泰山顶上跨年。为了心心念念的“Icame,Isaw,I conquered” 去克服内心一些...
    张洛伊阅读 260评论 0 0