如何从';与';python中的块

如何从';与';python中的块,python,sqlalchemy,Python,Sqlalchemy,我正在使用sqlalchemy创建一个事务。我将与一起使用,以利用自动提交和回滚功能: with session.begin(): do_stuff() 如果引发异常,在自动回滚后是否仍有传播该异常的方法?如果在with语句的主体中引发任何异常,则会立即调用\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu方法,并将该异常作为参数。然后,由\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

我正在使用sqlalchemy创建一个事务。我将
一起使用,以利用自动提交和回滚功能:

with session.begin():
    do_stuff()

如果引发异常,在自动回滚后是否仍有传播该异常的方法?

如果在
with
语句的主体中引发任何异常,则会立即调用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu方法,并将该异常作为参数。然后,由
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
决定是否正确处理了异常(通过返回一个真实值)

仅返回
None
,这表示可能在
with
语句的主体中引发的任何异常都将再次引发


请注意,由于任何函数的“默认”返回值都是
None
\uuuuu exit\uuuu
的默认行为是传播任何异常。没有任何用户级代码需要显式调用
\uuuuuuu exit\uuuuu
,或者查看其返回值,因此您确实需要特意返回真实值并抑制表达式


还要注意语句语义的描述:

以下代码:

with EXPRESSION as TARGET:
    SUITE
在语义上等同于:

manager = (EXPRESSION)
enter = type(manager).__enter__
exit = type(manager).__exit__ 
value = enter(manager)
hit_except = False

try:
    TARGET = value
    SUITE 
except:
    hit_except = True
    if not exit(manager, *sys.exc_info()):
        raise 
finally:
    if not hit_except:
        exit(manager, None, None, None)
try:
    context initialization
    do_stuff()
finally:
    contact cleanup
\uuuuu exit\uuuu
方法在两个互斥条件之一下调用:

  • 引发了异常,在这种情况下,在
    except
    子句中调用了异常。如果返回false,则重新引发捕获的异常
  • 未引发异常,在这种情况下,将在
    finally
    块中调用该异常
    hit_except
    is确保不会调用两次
    exit
    如果
    exit
    本身在
    except
    块中引发异常

  • 你不需要做任何特别的事情

    使用
    创建的上下文管理器大致相当于:

    manager = (EXPRESSION)
    enter = type(manager).__enter__
    exit = type(manager).__exit__ 
    value = enter(manager)
    hit_except = False
    
    try:
        TARGET = value
        SUITE 
    except:
        hit_except = True
        if not exit(manager, *sys.exc_info()):
            raise 
    finally:
        if not hit_except:
            exit(manager, None, None, None)
    
    try:
        context initialization
        do_stuff()
    finally:
        contact cleanup
    

    except:
    子句不同,
    finally:
    不会阻止异常的传播。它执行语句,然后继续传播。

    为什么您认为它不会自动传播?@Barmar假定
    会话
    有一个
    except
    子句来确定它是应该提交还是回滚。您将依靠它重新引发异常。或者可能不是,现在我想了一下,我不确定它的机制是如何工作的。我认为它使用了
    最后:
    进行清理操作,不是
    除了:
    @Barmar这是一个漫长的一天…我正在改变我启动事务的方式,我的单元测试失败了,因为没有引发验证…因为它被模拟了。
    \uuuuu exit\uuuu
    函数从未在模拟中出现。这很有帮助,它提醒我这是一个单元测试,实际上不是sqlalchemy,我模拟了
    \uuuu exit\uuu