sqlalchemy

Python中的with和context

2017-04-08  本文已影响58人  MontyOak

本文中所有代码均运行在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__来定义程序运行的环境,处理程序的进入和退出问题。

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

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
上一篇下一篇

猜你喜欢

热点阅读