Как обрабатывать исключения в python, используя оператор `with` в python? - PullRequest
0 голосов
/ 14 августа 2011

Предполагая этот кусок кода:

connection = get_some_connection() # maybe from oursql
with connection.cursor() as cursor:
    cursor.execute('some query')

Я понимаю, что после окончания cursor.close() будет выполнено автоматически. Как насчет исключений? Должен ли я положить их внутрь?

connection = get_some_connection() # maybe from oursql
with connection.cursor() as cursor:
    try:
        cursor.execute('some query')
    except IntegrityError, e:
        # handle exceoption

Или есть лучший способ справиться с ними с помощью оператора with?

Ответы [ 2 ]

4 голосов
/ 14 августа 2011

with x as y: z() в основном синтаксический сахар для:

y = x
y.__enter__()
try:
    z()
finally:
    if y.__exit__: y.__exit__()

Это не совсем точно, но в этом суть. Обратите внимание, что __exit__() будет передаваться информация об исключении, если было сгенерировано исключение (см. документы ), так что вы можете "обработать" исключение таким образом, но это не будет препятствовать тому, чтобы исключение было вызвано вызовом стек.

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

2 голосов
/ 14 августа 2011

В частном случае oursql ,

with some_connection.cursor() as cursor:
    do_something_with(cursor)

эквивалентно

cursor = some_connection.cursor()
try:
    do_something_with(cursor)
except:
    some_connection.rollback()
    raise
else:
    some_connection.commit()
finally:
    cursor.close()

Как вы можете видеть, зависит то, что делает оператор withв диспетчере контекста (например, some_connection.cursor () `).

with connection.cursor() as cursor:
    try:
        cursor.execute('some query')
    except IntegrityError as e:
        # handle exception

может или не может быть правильным способом обработки IntegrityError - вы можете захотеть обработать IntegrityError в некоторой внешней области видимости.

Например, если у вас есть какая-то общая функция, которая регистрирует запросы, такие как

def log_query(query):
    logger.info(query)
    with connection.cursor() as cursor:
        cursor.execute(query)

try:
    log_query(query)
except IntegrityError as err:
     # handler error

, вы можете не захотеть обрабатывать IntegrityError s внутри log_query, а скорее на более позднем этапе.

...