如何在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
语句来处理这些异常呢?
2 个回答
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
的方式可能是对的,也可能不是——你可能希望在外层的某个地方处理这个错误。
举个例子,如果你有一个通用的函数用来记录查询,比如说
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
你可能不想在log_query函数内部处理IntegrityError
,而是希望在后面的某个阶段处理它。
4
with x as y: z()
其实就是一种语法上的简化,意思差不多是:
y = x
y.__enter__()
try:
z()
finally:
if y.__exit__: y.__exit__()
虽然这不是完全准确的说法,但大致上就是这个意思。需要注意的是,如果发生了异常,__exit__()
会接收到异常的信息(具体可以查看文档),这样你就可以通过这种方式“处理”异常,但这并不会阻止异常继续向上抛出。
如果你想优雅地处理异常并且消耗掉它,你需要使用 try
/catch
结构。这个结构可以放在 with
块里面,也可以放在外面,只要在异常被抛出时,try 块是活跃的就可以。