• Python中的with语句


    ref:

    https://docs.python.org/release/2.6/whatsnew/2.6.html#pep-343-the-with-statement

    https://www.ibm.com/developerworks/cn/opensource/os-cn-pythonwith/

    https://www.python.org/dev/peps/pep-0343/

    摘自文档:

    with替代了之前在python里使用try...finally来做清理工作的方法。基本形式如下:

    with expression [as variable]:
        with-block

    当expression执行的时候,返回一个支持context management protocol(有__enter__(), __exit__()方法)的对象

    这个对象的__enter__()方法在with-block执行运行,该方法返回的结果赋给variable(如果variable存在的话)

    with-block执行之,__exit__()方法被调用,在这里可以执行清理工作

    If BLOCK raises an exception, the __exit__(type, value, traceback)() is called with the exception details

    with语句的运行过程如下:

    mgr = (EXPR)
    exit = type(mgr).__exit__  # Not calling it yet
    value = type(mgr).__enter__(mgr)
    exc = True
    try:
        try:
            VAR = value  # Only if "as VAR" is present
            BLOCK
        except:
            # The exceptional case is handled here
            exc = False
            if not exit(mgr, *sys.exc_info()):
                raise
            # The exception is swallowed if exit() returns true
    finally:
        # The normal and non-local-goto cases are handled here
        if exc:
            exit(mgr, None, None, None)

    也就是说:

    如果执行过程中没有出现异常,或者语句体中执行了语句 break/continue/return,

    则以 None 作为参数调用 __exit__(None, None, None) ;

    如果执行过程中出现异常,则使用 sys.exc_info 得到的异常信息为参数调用 __exit__(exc_type, exc_value, exc_traceback)

    出现异常时,如果 __exit__(type, value, traceback) 返回 False,则会重新抛出异常,让with 之外的语句逻辑来处理异常,这也是通用做法;如果返回 True,则忽略异常,不再对异常进行处理

    支持context management protocol的python对象有file object, threading locks variables, localcontext() fucntion in decimal module

    在文档里,有一个连接数据库的例子(省略了部分非关键代码):

    class DatabaseConnection:
        # Database interface
        def cursor(self):
            "Returns a cursor object and starts a new transaction"
        def commit(self):
            "Commits current transaction"
        def rollback(self):
            "Rolls back current transaction"
        def __enter__(self):
            # Code to start a new transaction
            cursor = self.cursor()
            return cursor
        def __exit__(self, type, value, tb):
            if tb is None:
                # No exception, so commit
                self.commit()
            else:
                # Exception occurred, so rollback.
                self.rollback()
                # return False

    然后就可以这样使用了:

    db_connection = DatabaseConnection()
    with db_connection as cursor:
        cursor.execute('insert into ...')
        cursor.execute('delete from ...')
        # ... more operations ...
  • 相关阅读:
    MyBatis框架(一)
    开始约定编程——Spring AOP
    Spring Boot快速入门
    全注解下的Spring IoC
    Java泛型
    Java异常
    windows监控web程序连接数
    winform导出excel报'object' does not contain a definition for 'get_Range'的问题
    git基本操作
    .net core中使用HttpClient碰到的问题:This instance has already started one or more requests. Properties can only be modified before sending the first request
  • 原文地址:https://www.cnblogs.com/geeklove01/p/9028909.html
Copyright © 2020-2023  润新知