2011-08-13 2 views
0

Предполагая, что этот кусок кода:Как обрабатывать исключения в python с помощью инструкции `with` в python?

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 

Или есть ли более удобный способ справиться с ними с помощью инструкции?

ответ

4

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

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

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

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

+0

Из-за того, как распространяется распространение исключения, не могли бы вы также сразу же «нарушить» '' '' '' '' '' '' '' '' 'with'? ;) –

+0

Да, абсолютно. Я уточню свой ответ, чтобы быть более ясным. – cdhowie

2

В частном случае 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 там внутри log_query, а на более позднем этапе.

+0

Обратите внимание, что если вы обрабатываете ошибку внутренне и не ре-рейзируете, тогда вам лучше обработать ее таким образом, который совместим с 'some_connection.commit()', который происходит, когда блок-блок курсора очищается :) –