Skip to main content
 首页 » 编程设计

python之在 SQLAlchemy Core 中使用 `with` 上下文管理器我如何知道事务是否回滚

2025年05月04日23lautakyan007

SQLAlchemy CORE doc for transactions建议使用 with 上下文管理器,如下所示:

# runs a transaction 
with engine.begin() as connection: 
    r1 = connection.execute(table1.select()) 
    connection.execute(table1.insert(), col1=7, col2='this is some data') 

或

with connection.begin() as trans: 
    r1 = connection.execute(table1.select()) 
    connection.execute(table1.insert(), col1=7, col2='this is some data') 

无论哪种方式,我如何知道事务是否已执行和提交,或者是否已回滚?

请您参考如下方法:

如果它没有提出,它 promise 。如果您查看文档,您会注意到 with 语句或多或少等同于:

connection = engine.connect() 
trans = connection.begin() 
try: 
    r1 = connection.execute(table1.select()) 
    connection.execute(table1.insert(), col1=7, col2='this is some data') 
    trans.commit() 
except: 
    trans.rollback() 
    raise 

关于评论:with 语句不一定是 try/except 的替代品,以防您需要异常处理——例如当您想知道事务是否回滚时。

如果您必须执行额外的清理或例如在事务回滚时记录日志,您仍然必须将 with 语句包装在 try/except 中,但您可以确定该事务之前已被处理控制从 with 语句控制的 block 传递:

try: 
    with ...: 
        ... 
 
except ...: 
    # rolled back 
 
else: 
    # committed 

您还可以选择重新引发错误,以便其他部分也可以处理它们的清理工作。当然,例如日志记录也可以由另一个上下文管理器处理:

from contextlib import contextmanager 
 
@contextmanager 
def logger(log, error_msg="Oh woe!"): 
    try: 
        yield 
 
    except: 
        log.exception(error_msg) 
        raise 
 
... 
 
with logger(log), connection.begin(): 
    r1 = connection.execute(table1.select()) 
    connection.execute(table1.insert(), col1=7, col2='this is some data') 

在本例中,正如您在评论中指出的那样,本着 PEP 343 的精神,通过使用 with 语句消除或隐藏了 try/except。 :

This PEP adds a new statement "with" to the Python language to make it possible to factor out standard uses of try/finally statements.