异常处理:将其置于

时间:2015-06-05 20:35:11

标签: python-2.7 exception-handling

这是一个普遍的概念性问题,不确定它是否适用于SO,但我会试一试。

我遇到过以下几次的情况,我从未确定如何处理它。

我有几个函数在一些层次结构中相互调用。我想处理函数的错误输入,但有些函数永远不会直接调用其他函数。

例如,我有这个功能:

def getDataSourcesOfTypes(username, datatypes):
    if len(datatypes) < 1:
        raise ValueError("Please specify at least 1 datatype")
    http = authorizeHttp(username)
    ...snip...
    return data_sources_list

这称之为:

def authorizeHttp(username):
    if not isinstance(username, str):
        raise ValueError("Invalid username.")
    credential_json = Database.getCredential(username)
    ...snip...      

反过来又称之为:

def getCredential(username):
    Database.connection.row_factory = sqlite.Row  # @UndefinedVariable
    cursor = Database.connection.cursor()
    ...snip...
    result = cursor.fetchone()
    if result is None:
        raise LookupError("Username does not exist.")
    else:
       ...snip...

现在,对于username,我有几次抓住坏的机会(即不是字符串,不存在等)。在我调用最后一个函数之前,显然我无法捕获它没有出现在数据库中的错误,但是我可以在第一个函数中找到None

问题是:捕获异常的最佳位置在哪里?在层次结构最远的层面?你能尽快吗?

同样,我认为对于SO来说这可能是一个主观问题,但我真的很好奇被认为是最佳做法。

2 个答案:

答案 0 :(得分:2)

有一般建议可供遵循。

  • 在可能修复的地方发现错误
  • 即使可能,也不要忽略异常(无except: pass
  • 记录
  • 请勿使用except:except Exception:
  • 等过于广泛的案例
  • 对不同的异常类型使用不同的异常块
  • 在需要的地方使用elsefinally
  • 例外是一种例外行为,不要使其符合逻辑 你的应用程序的一部分

这是关于异常处理的good articlePython docs也有最佳做法。那个from the past(但仍然有有效的信息)。

考虑到捕捉它们的地方。嗯,这里有不同的可能性。

  1. 您不能在代码中的任何其他位置使用任何这些功能 在这种情况下,请注意这个问题,意图是“我需要通知用户出了什么问题。这就是全部”。在这种情况下,可以在最高级别捕获异常。

  2. 在代码中广泛使用这些函数时,您需要采用不同的方法。像你一样引发异常,并在这个地方捕获它们,如果这是一个理想的行为,可以做任何事情来恢复正常的程序执行。或者,有时需要重新加注异常。例如:

    try:
         credential_json = Database.getCredential(username)
    except LookupError as le:
         log.warning(le)
         renew_token()  # (example) try to fix the problem somehow
         credential_json = Database.getCredential(username) # retry
         # note, that the next possible LookupError is not handled here.
    finally:
         check_data(credential_json)
    return credential_json
    
  3. 您正在编写可重用的代码。在这种情况下,它很复杂。一个 需要深入了解您的工作流程。你的代码必须 提供自定义异常,异常处理程序,这很容易 重写,控制返回值,提供后备等。

    def function_with_handler(data, error_handler=_handler, *args, **kwargs):
        try:
            do_stuff()
        except CustomError as such_problem:
            # log.level(such_problem)
            _handler(such_problem, data, *args, **kwargs)
    
  4. 此外,有时向fail_silently = True添加选项实际上是个好主意。

    阅读大型项目的源代码通常是一种很好的做法。例如,查看Django处理exceptions的方式。

答案 1 :(得分:0)

作为一般规则,我说,最接近错误的真正来源,它可以(可能)得到适当的处理。如果这是一个错误的输入,那么在输入的级别(也许在路上链接它)。如果这是字典中缺失键的预期异常,则立即捕获它。等

但当然,还有更多内容。