如何在Python中使用`with`语句处理异常?

0 投票
2 回答
543 浏览
提问于 2025-04-16 23:33

假设有这段代码:

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 块是活跃的就可以。

撰写回答