美文网首页sqlalchemy
Python中的with和context

Python中的with和context

作者: MontyOak | 来源:发表于2017-04-08 10:40 被阅读58次

    本文中所有代码均运行在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
    

    相关文章

      网友评论

        本文标题:Python中的with和context

        本文链接:https://www.haomeiwen.com/subject/qiclattx.html