Python 编码风格:错误检查和处理

Python coding style: Error checking and handling

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

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)
    

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

第一个显然是最简单的,但它有一个问题:如果套件其余部分中的任何其他东西可能会引发 ValueError,它就不是清楚你是否捕获了你期望和想要处理的ValueError,或者一个可能意味着你的代码中的错误的意外的,所以你可能应该让中止并打印回溯。

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

虽然确实如此,但您几乎可以肯定会像这样处理错误:

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 实际上是必需的。这是一个问题。 "predeclaring" 变量在设置它们之前的整个想法,然后检查它们是否已被设置,不仅不符合惯用,它还经常掩盖错误——例如,如果 None 是有效的 return 来自 decode?

"prefered coding style" 是 而不是 "handle" 错误,除非你能 真正地 处理它们。这意味着在库级别,您应该有几乎 none 错误处理 - 只需让错误传播到应用程序级别。在你想要的应用层面

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

  2. 你实际上可以要求用户更正的地方(再试一次,select 另一个文件,无论如何),做吧。

仅仅打印错误信息——没有完整的回溯等——只是在浪费大家的时间。