美文网首页
《Python基础教程》第8章 异常

《Python基础教程》第8章 异常

作者: tangyefei | 来源:发表于2015-01-15 11:30 被阅读328次

    本章将学习创建和引发自定义的异常,以及处理异常的各种方法。

    8.1 什么是异常

    程序运行中的错误或者不期望发生的事情就是异常,为了防止这样的事件你可以使用大量的条件语句,但是这样做的成本会非常高并且没效率。

    在Python中,用异常对象(exception object)来表示异常。如果异常对象未被处理或者捕捉,程序就会使用回溯(Traceback,一种错误信息)来终止程序。事实上每个异常都是一些异常类的实例,异常类的实例在不同情况被引发,并且都能够被捕捉到后进行错误处理,而不至于程序运行失败。

    8.2 按自己的方式出错

    8.2.1 raise语句

    有很多内建的异常类,详细介绍可以查询Python的文档“Built-in Exception”相关部分。

    可以使用dir列出exceptions模块内容:

    >>> import exceptions
    >>> dir(exceptions)
    ['ArithmeticError', 'AssertionError', ...]
    

    下面是使用内建异常类的简单例子:

    >>> raise Exception
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    Exception
    >>> raise Exception('hyperdriver overload')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    Exception: hyperdriver overload
    
    8.2.2 自定义异常类

    如果内建异常类不能满足程序的需求,可以自定义异常类。只需要保证自定义异常类是直接或者间接从Exception类继承的即可:

    class SomeCustomException(Expception): pass
    

    8.3 捕捉异常

    假如有一个要让用户输入两个数来整除的程序是这样的:

    n = input('Enter your first number:')
    m = input('Enter your second number:')
    print n / m
    
    
    $ python class.py
    Enter your first number:10
    Enter your second number:0
    Traceback (most recent call last):
      File "class.py", line 3, in <module>
        print n / m
    ZeroDivisionError: integer division or modulo by zero
    
    

    可以通过捕捉异常来处理它们:

    try:
        n = input('Enter your first number:')
        m = input('Enter your second number:')
        print n / m
    except ZeroDivisionError:
        print 'The second number can not be zero!'
    
    $ python class.py
    Enter your first number:10
    Enter your second number:0
    The second number can not be zero!
    

    我们虽然捕捉了异常并打印了信息,实际上却可以不处理它,而让它继续传递。

    如下是一个有 "屏蔽" ZeroDivisionError错误的代码示例。当muffled=Fasle时,会直接打印错误信息;否则异常会传递给上层调用者。

    
    class MuffledCalculator:
        muffled = False
        def calc(self, expr):
            try:
                return eval(expr)
            except ZeroDivisionError:
                if self.muffled:
                    print 'Division by zero is illegal.'
                else:
                    raise
    
    >>> c = MuffledCalculator()
    >>> c.calc("12/0")
    
    Traceback (most recent call last):
      File "class.py", line 12, in <module>
        c.calc("12/0")
      File "class.py", line 5, in calc
        return eval(expr)
      File "<string>", line 1, in <module>
    
    >>> c.muffled = true
    >>> c.calc("12/0")
    ZeroDivisionError: integer division or modulo by zero
    
    

    8.4 不止一个except子句

    在前面的例子中,还会有别情况,比如用户输入的如果是字符串,直接进行除法运算可能导致TypeError的异常,这时候就可以用多个except子句:

    try:
        n = input('Enter your first number:')
        m = input('Enter your second number:')
        print n / m
    except ZeroDivisionError:
        print 'The second number can not be zero!'
    except TypeError:
        print 'That was not number, is it?'
    

    8.5 用一个块捕捉两个异常

    上节中的多种异常情况如果不需要进行单独处理,能够更加简洁地用元组表示:

    try:
        n = input('Enter your first number:')
        m = input('Enter your second number:')
        print n / m
    except (ZeroDivisionError, TypeError, NameError):
        print 'Your number was bongus!'
    

    当然只是打印错误信息并没有什么意义,另一个方案就是要求用户输入合理的数字直到可以进行运算位为止。

    8.6 捕捉对象

    如果不想终止程序运行,又想在except子句中获取错误信息,可以直接访问异常对象:

    try:
        n = input('Enter your first number:')
        m = input('Enter your second number:')
        print n / m
    except (ZeroDivisionError, TypeError, NameError), e:
        print e
    
    
    $ python class.py
    Enter your first number:10
    Enter your second number:0
    integer division or modulo by zero
    

    8.7 真正的全捕捉

    总有一些用户操作会躲过try/except的检查,比如在上面的例子中,用户什么也不输入直接回车:

    $ python class.py
    Enter your first number:
    Traceback (most recent call last):
      File "class.py", line 2, in <module>
        n = input('Enter your first number:')
      File "<string>", line 0
        
        ^
    SyntaxError: unexpected EOF while parsing
    

    要Python对所有异常全部进行捕捉可以在except的子句中什么异常类也不写:

    try:
        n = input('Enter your first number:')
        m = input('Enter your second number:')
        print n / m
    except:
        print 'Something wrong happen...'
    

    8.8 万事大吉

    在try/except子句中,如果发生了exception会走except分支,如果没有发生exception,还可以新增一个else分支。如下示例:

    try:
        print 'A Simple Task'
    except:
        print 'What? Something went wrong!'
    else:
        print 'Ah... I went as planed'
    
    
    $ python class.py
    A Simple Task
    Ah... I went as planed
    

    8.9 最后

    除了else子句外,还有finally子句可以用来做一些清理工作(finally子句无论是否发生异常都会执行):

    try:
        1/o
    except NameError:
        print 'Unknown variable!'
    else:
        print 'That wents well'
    finally:
        print 'Clean up'
    
    $ python class.py
    Unknown variable!
    Clean up
    

    8.10 异常和函数

    如果异常在函数中没有被处理,就会被传播至函数调用的地方,如此层层往上直到被处理。

    8.11 异常之禅

    在某些时候try/except和if/else子句可以实现同样的功能,但是if/else自然性和可读性差些,应该养成尽可能的多使用try/except的习惯。

    “在做一件事情的过程中去处理可能出现的错误,而不是在做这件事情之前做大量的检查”。

    8.12 小结

    • 异常对象
    • 警告[注:该章压根就没提到警告好么]
    • 引发异常
    • 自定义异常类
    • 捕捉异常
    • else子句
    • 异常和函数
    8.12.1 本章的新函数

    8.12.2 接下来学习什么


    相关文章

      网友评论

          本文标题:《Python基础教程》第8章 异常

          本文链接:https://www.haomeiwen.com/subject/fldcxttx.html