【问题标题】:Correct extent of the exception handling block异常处理块的正确范围
【发布时间】:2016-10-25 10:19:50
【问题描述】:

假设我们有以下代码:

print("...")
might_throw_type_error()
print("...")
might_throw_index_error()

如果我们想处理这些函数可能出现的异常,首选的方法是什么:


完全拆分“业务”代码和错误处理

try:
    print("...")
    might_throw_type_error()
    print("...")
    might_throw_index_error()
except IndexError:
    # index error handling logic
    raise
except TypeError:
    # index error handling logic
    raise

逻辑和错误处理的拆分,但尝试从可能引发的第一条语句开始

print("...")
try:
    might_throw_type_error()
    print("...")
    might_throw_index_error()
except IndexError:
    # index error handling logic
    raise
except TypeError:
    # index error handling logic
    raise

异常处理应该只包装我们期望引发的语句

print("...")
try:
    might_throw_type_error()
except TypeError:
    # index error handling logic
    raise
print("...")
try:
    might_throw_index_error()
except IndexError:
    # index error handling logic
    raise

请注意,如果我们捕获异常,我们不想继续

【问题讨论】:

  • 这是相当基于意见的...Code Review 可能更适合此类问题。
  • 乐于移动它,询问是否有“pythonic”答案:$
  • 这真的不是 Pythonic 的问题,而是品味的问题。 CodeReview 可能会说同样的话。

标签: python exception error-handling code-readability


【解决方案1】:

这绝对取决于您到底想要实现什么 - 考虑一下,如果您将使用 #1 方法,如果第一个 might_throw_index_error 出现问题跟随print 和第二个might_throw_index_error 永远不会被执行。

另一方面,最后一个向您保证至少第二个 print 将始终触发。

这些方法中的每一种都很好,但这取决于您想对应用程序流做什么。

【讨论】:

  • 抱歉,忘记添加了。异常处理只是记录并重新引发(所以逻辑是相同的)。让我更新问题
  • 答案还是一样 - 唯一重要的是如果你想尝试触发第二种方法以防第一次失败 - 如果不是,没有理由不把它们放在一个 try-except
  • 所以你不同意“异常处理应该只包装我们期望引发的语句”这句话。这样做的理由是它让读者更清楚什么函数会引发特定类型的异常
  • 如果您看到 100 个 try-except 块一个接一个地比具有多个 except 的块更具可读性,那是您的选择。如果我有一个进程可以在多个地方被破坏,但绝对应该停止,以防万一我总是使用一个 try-except 块。
【解决方案2】:

创建一个 装饰器 并将该装饰器添加到您的每个函数定义中。查看A guide to Python's function decorators 了解详细信息。例如,你的装饰器应该是这样的:

def wrap_error(func):
    def func_wrapper(*args, **kwargs):
        try:
           return func(*args, **kwargs)
        except ValueError:
           # Some logic here
        except IndexError:
           # some logic here
    return func_wrapper

现在用你的函数定义添加这个装饰器:

@wrap_error
def function1():
    some code

现在您可以简单地调用函数:

function1()  # No need to handle the errors explicitly

无需担心每次调用时显式处理错误。

【讨论】:

  • “显式优于隐式”并且在装饰器中包装异常就像我所看到的那样隐含的可怕。
  • 视需求而定。我对此的看法略有不同。就我而言,这更好。假设您要将条目写入日志文件。后来要求发生了变化,现在您还需要发送电子邮件。你会去修改处理异常的每个地方的代码吗?它提供了一种更清洁的方式。你的函数代码与讨厌的 try/except 隔离,你的 main 函数很干净,装饰器坐在角落里管理所有讨厌的任务
猜你喜欢
  • 2018-08-26
  • 1970-01-01
  • 1970-01-01
  • 2012-07-06
  • 2023-03-07
  • 1970-01-01
  • 1970-01-01
  • 2021-03-16
  • 2016-08-21
相关资源
最近更新 更多