我经常在其他Stack Overflow问题上看到关于如何不鼓励使用except: pass的评论。这为什么不好呢?有时我不在乎错误是什么,我只想继续写代码。

try:
    something
except:
    pass

为什么使用except: pass块不好?是什么让它变得糟糕?是我传递了一个错误还是我排除了任何错误?


当前回答

In my opinion errors have a reason to appear, that my sound stupid, but thats the way it is. Good programming only raises errors when you have to handle them. Also, as i read some time ago, "the pass-Statement is a Statement that Shows code will be inserted later", so if you want to have an empty except-statement feel free to do so, but for a good program there will be a part missing. because you dont handle the things you should have. Appearing exceptions give you the chance to correct input data or to change your data structure so these exceptions dont occur again (but in most cases (Network-exceptions, General input-exceptions) exceptions indicate that the next parts of the program wont execute well. For example a NetworkException can indicate a broken network-connection and the program cant send/recieve data in the next program steps.

但是只对一个执行块使用pass块是有效的,因为你仍然可以区分不同类型的异常,所以如果你把所有的异常块放在一个中,它就不是空的:

try:
    #code here
except Error1:
    #exception handle1

except Error2:
    #exception handle2
#and so on

可以写成这样:

try:
    #code here
except BaseException as e:
    if isinstance(e, Error1):
        #exception handle1

    elif isinstance(e, Error2):
        #exception handle2

    ...

    else:
        raise

因此,即使是多个带有pass语句的异常块也可能导致代码,其结构处理特殊类型的异常。

其他回答

首先,它违背了Python的两个禅宗原则:

显性比隐性好 错误绝不能悄无声息地过去

它的意思是,你故意让你的错误悄无声息地过去。此外,您不知道究竟发生了哪个错误,因为except: pass将捕获任何异常。

其次,如果我们试图从Python的禅意中抽象出来,而只是从理智的角度来说话,你应该知道,使用except:pass会让你在系统中失去知识和控制。经验法则是,如果发生错误,就引发异常,并采取适当的操作。如果你事先不知道这些操作应该是什么,至少在某个地方记录错误(最好重新引发异常):

try:
    something
except:
    logger.exception('Something happened')

但是,通常情况下,如果您试图捕获任何异常,那么您可能正在做错误的事情!

为什么“except: pass”是一种糟糕的编程实践? 这为什么不好呢? 试一试: 某物 除了: 通过

这将捕获所有可能的异常,包括GeneratorExit、KeyboardInterrupt和SystemExit——这些异常可能是您不打算捕获的。这和捕获BaseException是一样的。

try:
    something
except BaseException:
    pass

旧版本的文档说:

由于Python中的每个错误都会引发异常,使用except:可以使许多编程错误看起来像运行时问题,从而阻碍调试过程。

Python异常层次结构

如果您捕获了一个父异常类,那么您也捕获了它们的所有子类。只捕获准备处理的异常要优雅得多。

下面是Python 3的异常层次结构——你真的想把它们都捕捉到吗?:

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StopAsyncIteration
      +-- ArithmeticError
      |    +-- FloatingPointError
      |    +-- OverflowError
      |    +-- ZeroDivisionError
      +-- AssertionError
      +-- AttributeError
      +-- BufferError
      +-- EOFError
      +-- ImportError
           +-- ModuleNotFoundError
      +-- LookupError
      |    +-- IndexError
      |    +-- KeyError
      +-- MemoryError
      +-- NameError
      |    +-- UnboundLocalError
      +-- OSError
      |    +-- BlockingIOError
      |    +-- ChildProcessError
      |    +-- ConnectionError
      |    |    +-- BrokenPipeError
      |    |    +-- ConnectionAbortedError
      |    |    +-- ConnectionRefusedError
      |    |    +-- ConnectionResetError
      |    +-- FileExistsError
      |    +-- FileNotFoundError
      |    +-- InterruptedError
      |    +-- IsADirectoryError
      |    +-- NotADirectoryError
      |    +-- PermissionError
      |    +-- ProcessLookupError
      |    +-- TimeoutError
      +-- ReferenceError
      +-- RuntimeError
      |    +-- NotImplementedError
      |    +-- RecursionError
      +-- SyntaxError
      |    +-- IndentationError
      |         +-- TabError
      +-- SystemError
      +-- TypeError
      +-- ValueError
      |    +-- UnicodeError
      |         +-- UnicodeDecodeError
      |         +-- UnicodeEncodeError
      |         +-- UnicodeTranslateError
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarning
           +-- ImportWarning
           +-- UnicodeWarning
           +-- BytesWarning
           +-- ResourceWarning

不要这样做

如果你使用这种形式的异常处理:

try:
    something
except: # don't just do a bare except!
    pass

然后你就不能用Ctrl-C来中断你的something块了。您的程序将忽略try代码块中所有可能的异常。

下面是另一个同样有不良行为的例子:

except BaseException as e: # don't do this either - same as bare!
    logging.info(e)

相反,尝试只捕获您知道正在寻找的特定异常。例如,如果你知道你可能会在一个转换中得到一个值错误:

try:
    foo = operation_that_includes_int(foo)
except ValueError as e:
    if fatal_condition(): # You can raise the exception if it's bad,
        logging.info(e)   # but if it's fatal every time,
        raise             # you probably should just not catch it.
    else:                 # Only catch exceptions you are prepared to handle.
        foo = 0           # Here we simply assign foo to 0 and continue. 

用另一个例子进一步解释

您可能会这样做,因为您已经进行了web抓取并得到了一个UnicodeError,但因为您使用了最广泛的异常捕获,您的代码可能有其他基本缺陷,将试图运行到完成,浪费带宽,处理时间,磨损您的设备,耗尽内存,收集垃圾数据等。

如果其他人要求你完成,这样他们就可以依赖你的代码,我理解那种被迫处理所有事情的感觉。但如果你愿意在开发过程中遭遇失败,你就有机会纠正那些偶尔出现的问题,但这将是代价高昂的长期错误。

有了更精确的错误处理,代码就会更加健壮。

我个人更喜欢这个解决方案:

except ValueError as error:
                print(error.args)
                pass

错误。Args给了我一个简单的代码行,它不会太分散人的注意力,但确实有助于代码审查,特别是如果错误有不同的原因,比如

(ValueError('year 0 is out of range'),)
(ValueError('month must be in 1..12'),)
(ValueError('day is out of range for month'),)

当研究熊猫的时间周期时。

如果这是糟糕的做法,“通过”就不会是一个选项。 如果你有一个资产,从许多地方接收信息IE一个表单或userInput,它就会派上用场。

variable = False
try:
    if request.form['variable'] == '1':
       variable = True
except:
    pass

这里的主要问题是它忽略所有和任何错误:内存不足,CPU正在燃烧,用户想要停止,程序想要退出,Jabberwocky正在杀死用户。

这太过分了。在你的脑海中,你在想“我想忽略这个网络错误”。如果出现了意想不到的错误,那么您的代码将继续以完全不可预测的方式中断,没有人可以调试。

这就是为什么您应该限制自己只忽略一些错误,而让其余的错误过去。