Используя менеджер контекста `with` в SQLAlchemy Core, как узнать, откатилась ли транзакция? - PullRequest
0 голосов
/ 04 июня 2018

Документ 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')

или

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

В любом случае, как это сделатьЯ знаю, была ли выполнена транзакция и была ли она совершена или откатан?

Ответы [ 2 ]

0 голосов
/ 04 июня 2018

Поскольку откат выполняется в случае исключения, если после кода with выполняется код, вы можете быть уверены, что транзакция не была откатана.

Если вам дополнительно необходимо test для этого случая вы можете использовать обычные конструкции python, такие как:

try:
    with connection.begin() as trans:
        r1 = connection.execute(table1.select())
        connection.execute(table1.insert(), col1=7, col2='this is some data')
except:
    # The transaction has been rolled back, you can log or otherwise
    # react to that fact
    ...
    # Finally, propagate the exception to the caller. If you choose not
    # to propagate, then don't use `except:`, but handle a narrower
    # class of exceptions.
    raise
0 голосов
/ 04 июня 2018

Если оно не поднимается, оно совершается.Если вы посмотрите документы, вы заметите, что оператор 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 /за исключением случаев, когда вам нужна обработка исключений - например, когда вы хотите знать, откатана ли транзакция или нет.

Если вам придется выполнить дополнительную очистку или, например, вести журнал при откате транзакции, вы все равнонеобходимо заключить оператор with в попытку / исключение, но вы можете быть уверены, что транзакция была обработана до того, как управление переходит из блока, управляемого оператором with:

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')

В этом случае, как вы заметили в комментарии, попытка / исключение была исключена или скрыта с помощью оператора with, в духе PEP 343 :

Этот PEP добавляет новое выражение "with" в язык Python, чтобы можно было выделить стандартные применения try /наконец, заявления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...