简体   繁体   English

如何从 python 中的“with”块中引发异常

[英]How to raise an exception from within an 'with' block in python

I'm using sqlalchemy to create a transaction.我正在使用 sqlalchemy 创建事务。 I'm using with to take advantage of the auto commit and rollback:我正在使用with来利用自动提交和回滚:

with session.begin():
    do_stuff()

If an exception is raised, is there anyway to propagate that exception after the auto rollback?如果引发异常,是否在自动回滚后传播该异常?

If any exception is raised during the body of a with statement, the __exit__ method is immediately called with that exception as an argument.如果在with语句的主体期间引发任何异常,则立即调用__exit__方法,并将该异常作为参数。 It is up to __exit__ to then decide whether the exception has been properly handled (by returning a truthy value) or whether it should be re-raised after __exit__ completes (by returning a non-truthy value).然后由__exit__决定是否已正确处理异常(通过返回真实值)或是否应在__exit__完成后重新引发(通过返回非真实值)。

SessionTransaction.__exit__ only returns None , which indicates that any exception that may have been raised in the body of the with statement will be raised again. SessionTransaction.__exit__只返回None ,这表明在with语句的主体中可能已经引发的任何异常都将再次引发。


Note that since the "default" return value of any function is None , the default behavior of __exit__ is to propagate any exceptions.请注意,由于任何 function 的“默认”返回值为None ,因此__exit__的默认行为是传播任何异常。 No user-level code is expected to call __exit__ explicitly or look at its return value, so you really have to do out of your way to return a truthy value and suppress an expression.用户级代码不应显式调用__exit__或查看其返回值,因此您必须竭尽全力返回真实值并抑制表达式。


Also note the description of the with statement's semantics:还要注意with语句语义的描述:

The following code:以下代码:

 with EXPRESSION as TARGET: SUITE

is semantically equivalent to:在语义上等价于:

 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)

The __exit__ method is called under one of two mutually exclusive conditions: __exit__方法在两个互斥条件之一下被调用:

  1. An exception was raised, in which case it was called in the except clause.引发了一个异常,在这种情况下,它在except子句中被调用。 If it returns false, the caught exception is re-raised.如果它返回 false,则重新引发捕获的异常。
  2. An exception was not raised, in which case it is called in the finally block.没有引发异常,在这种情况下,它在finally块中被调用。 hit_except is ensures that exit is not called twice if exit itself raises an exception in the except block. hit_except确保如果exit本身在except块中引发异常,则不会调用两次exit

You shouldn't need to do anything special.你不应该做任何特别的事情。

Context managers created using with are roughly equivalent to:使用with创建的上下文管理器大致相当于:

try:
    context initialization
    do_stuff()
finally:
    contact cleanup

Unlike an except: clause, finally: doesn't block propagation of the exception.except:子句不同, finally:不会阻止异常的传播。 It executes the statements and then continues propagation.它执行语句,然后继续传播。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM