在Python中为何要使用except:
在Python中,使用 except Exception as ex
或 except BaseException as ex
是不是和 except:
一样,只不过你可以得到一个异常的引用呢?
根据我的理解,BaseException
是一个更新的默认捕获所有异常的方式。
除了这个,为什么你还会想要单独使用 except:
这个语句呢?
5 个回答
除了这个,为什么你会想要单独使用一个
except:
语句呢?
简单来说:你其实不需要这样做。
详细说说:如果你只用一个简单的 except:
,就没法区分不同的错误了。而且,想要获取错误的具体信息也会变得更困难。所以通常我们会使用 except ExceptionType as e:
这种写法。
其实不是这样的。
如果你去看看Python的文档,特别是关于内置异常的部分(可以参考这一块),你会看到各种异常是从哪里继承来的。如果你用原始的except:,它会捕捉到所有抛出的异常,包括KeyboardInterrupt(也就是你按下Ctrl+C时的中断),这通常是你不想捕捉的;如果你用except BaseException as exp:,同样的情况也会发生,因为所有异常都是从它继承的。
如果你想捕捉所有程序运行时的异常,正确的做法是用except Exception as exp:,这样就不会捕捉到那些你希望程序结束时抛出的异常(比如KeyboardInterrupt)。
现在,有人会告诉你这样捕捉所有异常是个坏主意,通常他们是对的;不过如果你有一个程序在处理大量数据时,你可能希望它在遇到异常时不要直接退出。只要你妥善处理这些异常(比如记录下来,并确保用户知道发生了异常),但绝对不要只是用pass跳过;如果你的程序出现了你不知道的错误,它可能会表现得非常奇怪!
如果你真的不在乎失败的原因或错误信息,你可以用一个简单的 except:
。有时候,这样做是有用的,比如你想使用一些可能存在也可能不工作的功能。如果它失败了,你打算优雅地转向其他的代码路径。在这种情况下,错误的类型或信息对你接下来要做的事情没有影响。
除了“宝可梦”异常处理*是个坏主意之外,还有几个不同之处。
在Python 2中,except Exception:
和except BaseException:
都无法捕获旧式类异常:
>>> class Foo(): pass
...
>>> try:
... raise Foo()
... except Exception:
... print 'Caught'
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
__main__.Foo: <__main__.Foo instance at 0x10ef566c8>
>>> try:
... raise Foo()
... except BaseException:
... print 'Caught'
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
__main__.Foo: <__main__.Foo instance at 0x10ef56680>
>>> try:
... raise Foo()
... except:
... print 'Caught'
...
Caught
这是因为旧式对象并不是从BaseException
或Exception
派生的。因此,任何情况下都不应该使用不从Exception
派生的自定义异常。
接下来,有三个异常是从BaseException
派生的,但不是从Exception
派生的;在大多数情况下,你不想捕获这些异常。SystemExit
、KeyboardInterrupt
和GeneratorExit
这些异常在正常的异常处理过程中通常是不需要捕获的。如果你使用except BaseException:
,你会捕获到这些异常,而except Exception
则不会。
* “宝可梦”异常处理是因为你必须“捕获所有”。
这三者之间的区别是:
- 光秃秃的
except
会捕捉到所有东西,包括像KeyboardInterrupt
这样的系统退出事件; except Exception[ as ex]
会捕捉到任何Exception
的子类,这应该包括你自己定义的所有异常和 所有内置的非系统退出异常;except BaseException[ as ex]
和光秃秃的except
一样,会捕捉到绝对所有的异常。
一般来说,我建议使用第二种方式(理想情况下是在捕捉到特定的“预期”错误后作为备用),因为这样可以让那些系统退出的异常上升到更高的层级。正如你所说,第二和第三种方式中的 as ex
部分让你在处理错误时可以检查这个错误。
这里有一篇关于“except 的坏处”的有用文章,点击这里可以查看。