【问题标题】:Python coding style: Error checking and handlingPython 编码风格:错误检查和处理
【发布时间】:2015-04-17 20:07:36
【问题描述】:

我正在用 python 编写一些软件,并且对 python 的首选编码风格有疑问。 想象一下,您有一个函数,它获取一些原始数据,将其解码为 dict 并打印键值对

def printdata(rawdata):
    data = decode(rawdata)
    for key, value in data.items():
        print(key, value)

这一切都很好,直到decode 开始到处抛出异常并且整个程序崩溃了。因此,我们使用 try/catch 块。但是有几种方法可以做到这一点,我想知道哪种方法更受欢迎。

  1. try里面的所有东西

    def printdata(rawdata):
        try:
            data = decode(rawdata)
            for key, value in data.items():
               print(key, value)
        except ValueError:
            print("error")
    
  2. decodetryreturn

    def printdata(rawdata):
        data = None
        try:
            data = decode(rawdata)
        except ValueError:
            print("error")
            return
        for key, value in data.items():
           print(key, value)
    
  3. 只有decodetryif

    def printdata(rawdata):
        data = None
        try:
            data = decode(rawdata)
        except ValueError:
            print("error")
        if data is not None:
            for key, value in data.items():
               print(key, value)
    

所有这些方法都有一些优点和缺点,我不知道该选择哪一种,以及它是否真的重要。

【问题讨论】:

  • 虽然 1 不等于 2 或 3,但没关系。使用对您来说看起来不错并且具有您想要的逻辑的那个。捕获所有 ValueErrors 与仅从 decode() 捕获 ValueErrors 不同。

标签: python coding-style


【解决方案1】:

第一个显然是最简单的,但它有一个问题:如果套件中的其他任何东西都可能引发ValueError,则不清楚你是否抓住了@987654323 @您期望并想要处理,或者可能意味着您的代码中存在错误的意外问题,因此您可能应该让中止并打印回溯。

当你确定这不是问题时,就去做吧。

虽然真的,你几乎肯定应该像这样处理错误:

except ValueError as e:
    print("error: {!r}".format(e))

……或类似的东西。这样,如果您确实收到了不可能的意外ValueError,您将能够从意外消息中判断出来,而不是不知道您因为错误而丢弃了有效数据过去 3 个月的运行。


如果这不合适,其他两个想法都工作,但使用else 块通常更惯用。

def printdata(rawdata):
    try:
        data = decode(rawdata)
    except ValueError:
        print("error")
    else:
        for key, value in data.items():
           print(key, value)

如果你确实需要做#2(也许你有,比如说,try 语句里面有一堆 try 语句或其他东西......),你不需要顶部的 data = None,不应该拥有它。 应该如果不分配给data,您将无法通过return。所以,如果不可能的事情发生了,你想得到一个异常并看到它,而不是默默地把它当作None


在#3 中,None 实际上是必需的。这是一个问题。在设置变量之前“预先声明”变量,然后检查它们是否已设置的整个想法不仅不惯用,而且还经常掩盖错误——例如,如果None 是来自decode 的有效返回怎么办?

【讨论】:

  • 哇,我什至不知道你可以在 try/except 之后有一个 else 子句。这绝对是最好的选择。谢谢! print("error") 只是为了保持示例简单,不用担心。
  • @Dokahl:当您尝试了解有关某些语言功能的更多信息时,请始终首先使用check the docs。 :)
  • @abarnert:我简直不敢相信建议只打印错误并收工,而不是让它传播到可以处理的地方。有史以来最愚蠢的“错误处理”方案:(
  • @brunodesthuilliers:我认为你没有理解这个建议。看第一句话。那是关键。因此,如果设计目标是记录并忽略来自decode的可能特定ValueError那么最重要的考虑不是样式,而是确保您正在记录并忽略仅该特定错误。通过仔细考虑结构来确保双重确定,然后通过记录足够的信息来确保三重确定,如果你没有想到什么。
【解决方案2】:

“首选编码风格”是“处理”错误,除非您可以真正处理它们。这意味着在库级别,您应该几乎没有错误处理 - 只是让错误传播到应用程序级别。在您想要的应用程序级别

  1. 一个顶级错误处理程序,将正确记录未处理的错误完整的回溯logging.exception() 是你的朋友),向用户显示用户友好的错误消息并崩溃。

  2. 您实际上可以要求用户进行更正(再试一次,选择另一个文件,无论如何),请执行此操作。

仅打印错误消息 - 没有完整的回溯等 - 只是浪费每个人的时间。

【讨论】:

  • 我认为这与这里无关。大概他有理由想要记录并忽略这些解码错误。例如,可能有 3% 的数据是乱码,他想继续处理 97% 的数据。在这种情况下,编写一行日志消息并继续前进是非常有意义的。
  • 更一般地说,这个建议似乎适用于与 Python 完全不同的语言。在 Python 中,异常会到处抛出。每个for 循环都以异常结束。因此,“始终记录有关每个异常的所有信息”不适用于 Python。 “始终记录有关每个意外异常的所有信息”仍然是绝对正确的——但最简单的方法是,只要它适合您的应用程序,就是不要捕获意外异常并让它们中止并打印回溯。
猜你喜欢
  • 2013-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-18
  • 2010-10-03
相关资源
最近更新 更多