2011-08-13 63 views
0

假定這一段代碼:如何在python中使用`with`語句處理異常?

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語句?

回答

4

with x as y: z()基本上是語法糖:

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

這並不完全準確,但是這是它的要點。請注意,如果拋出異常(請參閱the docs),__exit__()將傳遞異常信息,因此您可以通過這種方式「處理」異常,但這不會阻止異常拋出調用堆棧。

如果要優雅地處理異常並使用它,則需要使用try/catch塊。它可以位於with塊內部或外部,只要try塊在引發異常時處於活動狀態即可。

+0

由於異常是如何傳播的,您是否也可以不在''with'塊之外立即**'try' /'catch'? ;) –

+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()兼容的方式處理它,當光標的with-block清理完成時會發生這種情況:) –