python基础教程_学习笔记10:异常

异常

什么是异常

Python用异常对象来表示异常情况。遇到错误后,会引发异常。如果异常对象并未被处理或捕捉,程序就会用所谓的回溯(Traceback,一种错误信息)终止执行:

>>> 1/0

 

Traceback (most recent call last):

  File "", line 1, in 

    1/0

ZeroDivisionError: integer division or modulo by zero

 

每个异常都是一些类的实例,这些实例可以被引发,并且可以用很多方法进行捕捉,使得程序可以捉住错误并对其进行处理,而不是让整个程序失败。

 

按自己的方式出错

异常可以在某些东西出错时自动引发

raise语句

为了引发异常,可以使用一个类(应该是Exception的子类)或者实例参数调用raise语句。使用类时,程序会自动创建实例。

>>> raise Exception

 

Traceback (most recent call last):

  File "", line 1, in 

    raise Exception

Exception

>>> raise Exception('hyperdrive overload')

 

Traceback (most recent call last):

  File "", line 1, in 

    raise Exception('hyperdrive overload')

Exception: hyperdrive overload

 

第一个例子引发了一个没有任何有关错误信息的普通异常;

第二个例子则添加了一些hyperdive overload错误信息。

 

内建的异常类有很多。

>>> import exceptions

>>> dir(exceptions)

['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BufferError', 'BytesWarning', 'DeprecationWarning', 'EOFError', 'EnvironmentError', 'Exception', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '__doc__', '__name__', '__package__']

 

所有这些异常都可以用于raise语句:

>>> raise ZeroDivisionError

 

Traceback (most recent call last):

  File "", line 1, in 

    raise ZeroDivisionError

ZeroDivisionError

>>> raise BaseException

 

Traceback (most recent call last):

  File "", line 1, in 

    raise BaseException

BaseException

 

一些最重要的内建异常类

类名 描述
Exception 所有异常的基类
AttributeError 特性引用或赋值失败时引发
IOError 试图打开不存在的文件(包括其他情况)时引发
IndexError 在使用序列不存在的索引时引发
KeyError 在使用映射中不存在的键时引发
NameError 在找不到名字(变量)时引发
SyntaxError 在代码为错误形式时引发
TypeError 在内建操作或函数应用于错误类型的对象时引发
ValueError 在内建操作或者函数应用于正确类型的对象,但该对象使用不合适的值时引发
ZeroDivisionError 在除法或模除操作的第二个参数为0时引发

自定义异常类

有些时候需要创建自己的异常类。

class SomeCustomException(Exception): pass

可以向自动义异常类中增加方法,此处什么也没做。

 

捕捉异常

关于异常最有意思的地方就是可以处理它们(通常叫做诱捕或者捕捉异常)。

这个功能可以使用try/except来实现。

 

x=input(‘1st number: ’)

y=input(‘2nd number: ’)

print x/y

 

如果用户输入0作为第二个数,则出现ZeroDivisionError异常。

 

为了捕捉异常并且做出一些错误处理:

try:

x=input(‘1st number: ’)

y=input(‘2nd number: ’)

print x/y

except ZeroDivisionError:

print “The 2nd number can’t be zero!”

 

看,没参数

>>> 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

 

>>> calculator=MuffledCalculator()

>>> calculator.calc('10/2')

5

>>> calculator.calc('10/0')

 

Traceback (most recent call last):

  File "", line 1, in 

    calculator.calc('10/0')

  File "", line 5, in calc

    return eval(expr)

  File "", line 1, in 

ZeroDivisionError: integer division or modulo by zero

>>> calculator.muffled=True

>>> calculator.calc('10/0')

Division by zero is illegal

不止一个except子句

try:

x=input(‘1st number: ’)

y=input(‘2nd number: ’)

print x/y

except ZeroDivisionError:

print “The 2nd number can’t be zero!”

 

如果用户输入“HelloWorld”作为第二个参数,将引发错误:

TypeError: unsupported operand type(s) for /: 'int' and 'str'

因为except子句只寻找ZeroDivisionError异常,这次的错误就溜过了检查并导致程序终止。为了捕捉这个异常,可以直接在同一个try/except语句后面加上另一个except子句:

try:

x=input(‘1st number: ’)

y=input(‘2nd number: ’)

print x/y

except ZeroDivisionError:

print “The 2nd number can’t be zero!”

except TypeError:

print “That wasn’t a number,was it?”

用一个块捕捉两个异常

如果需要用一个块捕捉多个类型异常,可以将它们作为元组列出:

 

try:

x=input(‘1st number: ’)

y=input(‘2nd number: ’)

print x/y

except (ZeroDivisionError,TypeError):

print “Your numers are bogus!”

捕捉对象

如果想让程序继续运行,但是又因为某种原因想记录下错误,捕捉对象就很有用。

 

try:

x=input(‘1st number: ’)

y=input(‘2nd number: ’)

print x/y

except (ZeroDivisionError,TypeError),e:

print e

真正的全捕捉

就算程序能处理好几种类型的异常,但有些异常还是会从眼皮底下溜走。

 

以除法为例子,在提示符下直接按回车,不输入任何东西,会得倒一个类似下面的错误信息:

SyntaxError: unexpected EOF while parsing

 

这个异常逃过了try/except语句的检查。这种情况下,与其用那些并非捕捉这些异常的try/except语句隐藏异常,还不如让程序立刻崩溃。

 

但如果真的想用一段代码捕获所有异常,可以在except子句中忽略所有的异常类:

try:

x=input(‘1st number: ’)

y=input(‘2nd number: ’)

print x/y

except:

print ‘Something wrong happened...’

 

警告:像这样捕捉所有异常是危险的,因为它会隐藏所有程序员未想到并且未做好准备处理的错误。它同样会捕捉用户终止执行的Ctrl+c企图,以及用sys.exit函数终止程序的企图,等等。这时用except Exception,e会更好些,或者对异常对象e进行一些检查。

万事大吉

有些情况下,一些坏事发生时执行一段代码是很有用的,可以给try/except语句加个else子句:

>>> try:

print 'A simple task'

except:

print 'what?'

else:

print 'nothing'

 

 

A simple task

nothing

最后......

finally子句,用来在可能的异常后进行清理。

 

>>> try:

print 'A simple task'

except:

print 'what?'

else:

print 'nothing'

finally:

print 'clean up'

 

A simple task

nothing

clean up

异常和函数

异常和函数很自然地一起工作。如果异常在函数内引发而不被处理,它会传播至函数调用的地方。如果在那里也没有处理异常,它会继续传播,一直到达主程序(全局作用域)。如果那里没有异常处理程序,程序会带着堆栈跟踪终止。

 

>>> def faulty():

raise Exception('something is wrong')

 

>>> def ignore_exception():

faulty()

 

>>> def handle_exception():

try:

faulty()

except:

print 'Exception handled'

 

>>> ignore_exception()

 

Traceback (most recent call last):

  File "", line 1, in 

    ignore_exception()

  File "", line 2, in ignore_exception

    faulty()

  File "", line 2, in faulty

    raise Exception('something is wrong')

Exception: something is wrong

>>> handle_exception()

Exception handled

你可能感兴趣的:(python,python零基础)