事务的SQLAlchemy CORE 文档建议使用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')
Run Code Online (Sandbox Code Playgroud)
或者
with connection.begin() as trans:
r1 = connection.execute(table1.select())
connection.execute(table1.insert(), col1=7, col2='this is some data')
Run Code Online (Sandbox Code Playgroud)
无论哪种方式,我如何知道事务是否已执行并提交,或者是否已回滚?
如果它没有提高,它就承诺了。如果您查看文档,您会注意到 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
Run Code Online (Sandbox Code Playgroud)
关于评论:with 语句不一定是 try/except 的替代品,以防您需要异常处理——例如当您想知道事务是否回滚时。
如果您必须执行额外的清理或例如在事务回滚时进行日志记录,您仍然需要将 with 语句包装在 try/except 中,但您可以确保在控制传递之前事务已被处理由 with 语句控制的块:
try:
with ...:
...
except ...:
# rolled back
else:
# committed
Run Code Online (Sandbox Code Playgroud)
您还可以选择重新引发错误,以便其他部分也可以处理它们的清理工作。当然,例如日志记录也可以由另一个上下文管理器处理:
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')
Run Code Online (Sandbox Code Playgroud)
在这种情况下,正如您在评论中指出的那样,本着PEP 343的精神,通过使用 with 语句消除或隐藏了 try/except :
这个 PEP 向 Python 语言添加了一个新的“with”语句,以便可以分解出 try/finally 语句的标准用法。