Python 101:异常处理

原文地址:http://www.blog.pythonlibrary.org/2012/09/12/python-101-exception-handling/

Python提供一个强大的异常处理机制。异常处理是每个程序员需要学习的东西。它允许程序员在发生异常的时候继续他们的程序或正常地终止应用程序。 Python使用了try/except/finally声明。我们将花一些时间学习有关标准异常,如何创建一个自定义的异常,以及如何获得异常信息,以便进行调试的时候需要到它。

基本的异常处理


首先必须说,直接的异常处理(捕捉所有异常)是通常不推荐!你会看到如何使用直接的异常处理(捕捉所有异常),但我从来不会使用到它。直接的异常(捕捉所有异常)处理看起来像这样:

try:
    print monkey
except:
    print "This is an error message!"

正如你可以看到的,这将捕获所有异常,但你真的不知道任何有关异常的信息,因此处理起来相当棘手。因为你不知道什么异常被捕捉了,也不能打印出一个非常有用的信息给用户。但是从另外一方面来说,如果有些时候使用最直接的异常处理(捕捉所有的异常)的话也许还是有些作用的,我的一个读者指出:数据库的交互就是使用这种情况的最好场景。我发现我在处理数据库的时候通常会用到很宽泛的异常,因此我也对读者的观点表示一定的赞同。

让我们来看看一些正常的异常处理的例子:
try:
    import spam
except ImportError:
    print "Spam for eating, not importing!"
 
try:
    print python
except NameError, e:
    print e
 
try:
    1 / 0
except ZeroDivisionError:
    print "You can't divide by zero!"

  • 第一个例子在导入spam的时,如果python没有找到它的时候会触发。一个很好的使用这种异常处理的场景就是导入一个替换模块。像python2.5以及以上的版本,导入md5模块会抛出ImportError异常,因为这个模块已经被hashlib 替换了。
  • 另一个例外是NameError。当一个变量没有被定义,你就会得到这个异常。您还会注意到,我们在异常的部分增加了一个逗号和“e”。这让我们不仅能够捕获到错误,还能打印出来的异常信息,在这个例子中的异常信息是name ‘python’ is not defined。
  • 第三个也是最后一个异常是如何捕捉零作为分母的一个例子。是的,不管如何,用户仍然试图除以零,往往你告诉他们不要。
现在,如果你想捕获多个错误但不是所有的错误,你会怎么做?让我们来看看!
try:
    5 + "python"
except TypeError:
    print "You can't add strings and integers!"
except WindowsError:
    print "A Windows error has occurred. Good luck figuring it out!"
finally:
    print "The finally section ALWAYS run!"

在上面的代码中,你们将看到在一个try下有两个except声明。您可以添加尽可能多的异常当你想要或需要做的时候。

获取整个堆栈回溯

如果你想获得整个追踪的异常怎么办?Python有一个模块能达到这个目的,这就是所谓的、逻辑的traceback。这里有一个快速的小例子:
import traceback
 
try:
    with open("C:/path/to/py.log") as f:
        for line in f:
            print line
except IOError, exception:
    print exception
    print 
    print traceback.print_exc()

上面的代码将打印出异常信息,打印一个空行,然后打印整个追踪使用traceback模块的print_exc的方法。还有一堆其他方法在traceback模块,让您的自定义输出格式或获得各个部分的堆栈跟踪。更多细节和例子,但你应该检查出的文档


还有另一种方法,得到整个回溯不使用traceback模块,至少不直接。相反,您可以使用Python的日志记录模块。下面是一个简单的例子:
import logging
 
logging.basicConfig(filename="sample.log", level=logging.INFO)
log = logging.getLogger("ex")
 
try:
    raise RuntimeError
except RuntimeError, err:
    log.exception("RuntimeError!")

这将创建一个日志文件在同一目录下,在运行该脚本中包含以下内容:
ERROR:ex:RuntimeError!
Traceback (most recent call last):
File "C:\Users\mdriscoll\Desktop\exceptionLogger.py", line 7, in <module>
raise RuntimeError
RuntimeError

创建一个自定义的异常

当你编写复杂的程序,你可能会发现需要创建自己的异常。幸运的是,在Python中编写一个新的异常是一个很容易的过程。这里有一个很简单的例子:
class ExampleException(Exception):
    pass
 
try:
    raise ExampleException("There are no droids here")
except ExampleException, e:
    print e


结束语

现在你应该知道如何捕获异常,使用traceback,甚至可以创建自己的自定义异常。学会这些,即使不好的事情发生!你的脚本将会继续运行。当然,他们也不会帮助,如果电源熄灭(哈哈哈,这是一个玩笑)!学会处理异常能够强化你的代码,能够确保许多不同的情况下你的程序不会崩溃。