美文网首页
《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