天天看点

python之异常

8.1 什么是异常

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

>>>1/0

报错

如果这些错误信息就是异常的全部功能,那么它也就不必存在了。事实上,每个异常都是一个类的实例,这些实例可以被引发,并且可以用很多种方法进行捕捉,使得程序可以捉住错误并且对其进行处理,而不是让整个程序失败。

8.2.1 raise 语句

为了引发异常,可以使用一个类(exception的子类)或者实例参数调用raise语句。使用类时,程序自动创建实例。下面的例子,使用了内建的exception异常类:

>>>raise Exception

普通异常

>>>raise Exception('abc')

报abc异常错误

可以使用dir函数列出模块的内容

>>>import exceptions

>>>dir(exceptions)

['ArithmeticError','AssertionError','AttributeError',...]

所有这些异常都可以用在raise中

>>>raise ArithmeticError

8.2. 自定义异常类

class SomeCustomException(Exception):pass

8.3 捕捉异常

try:

x = input('Enter the first number:')

y = input('Enter the second number:')

print x/y

except ZeroDivisionError:

print "The second number can't be zero"

如果没有捕捉异常,它就会被传播到调用的函数中。如果在那里依然没有捕获,这些异常就会浮到程序的最顶层。也就是说你可以捕捉到在其他人的函数中所引发的异常。

class MuffledCalculator:

muffled = False

def calc(self,expr):

return eval(expr)

if self.muffled:

print 'Division by zero is illegal'

else:

raise

捕捉到了异常,但是又想重新引发它(传递异常),可以使用不带参数的raise语句。

下面是这个类的用法示例,分别打开和关闭了屏蔽:

>>>calculator = MuffledCalculator

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

5

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

>>>calculator.muffled = True

当计算器没有打开屏蔽机制时,ZeroDivisionError被捕捉但已传递了。

8.4 不止一个except 子句

    print 2/'0'

    print '除数不能为0'

except Exception:

    print '其他类型异常'

8.5 用一个块捕捉两个异常

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

except (ZeroDivisionError,TypeError):

    print '发生了一个异常'

8.6 获取异常

except (ZeroDivisionError,Exception) as e:

    print e 

在python3.0中,except子句会被写作except(ZerDivisionError,TypeError) as e.

8.7 捕捉所有异常

except:

    print 'Something wrong happened。。'

这样做是危险的,因为它会隐藏所有程序员未想到并且未做好准备处理的错误。

8.8 运用循环在异常

print 'A simple task'

print 'What? Something went weong?'

print 'Ah...It went as planned.'

使用else子句:

while True:

value = x/y

print 'x/y is',value

print 'Invalid input,Please try again.'

break

这里的循环只在没有异常处理的情况下才会退出。换句话说,只要发生错误,程序会不断要求重新输入。

可以使用空的except子句来捕捉所有Exception类的异常(也会捕捉其所有子类的异常)。百分之百捕捉到所有的异常时不可能的,因为try/except语句中的代码可能会出问题,比如使用旧风格的字符串异常或自定义的异常类不是Exception类的子类。不过如果需要使用except Exception的话,可以使用打印的方法来显示错误信息:

except Exception,e:

print 'Invalid input:',e

print 'Please try again'

8.9 finally 子句

最后finally子句,它可以用来在可能的异常后进行清理。它和try子句联合使用:

x = None

x = 1/0

finally:

print 'Cleaning up...'

del x

上面的代码中,finally子句肯定会被执行,不管子句try子句中是否发生异常。

使用del语句删除一个变量是非常不负责的清理手段,所以finally子句用于关闭文件或者网络套接字时会非常有用。还可以在同一条语句中组合使用try,except,finally和else。

1/0

except NameError:

print "Unknown variable"

print "That went well!"

print "Cleaning up."

8.10 异常和函数

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

>>>def faulty()

raise Exception('Something is wrong')

>>>def ignore_exception():

faulty()

>>>def handle_exception():

print 'Exception handled'

>>>ignore_exception()

>>>handle_exception()

Exception handled

可以看到,faulty中产生的异常通过faulty和ignore_exception传播,最终导致了堆栈跟踪。同样的,它也传播到了handle_exception,但在这个函数中被try/except语句处理.

8.11 异常之禅

def describePerson(person):

print 'Description of',person['name']

print 'Age:',person['age']

print 'Occupation:' + person['occupation']

except KeyError: pass

这里在打印职业时使用加号而不是逗号,否则字符串'Occupation:'在异常引发之前就会被输出。

这个程序直接假定'occupation'键存在。如果他的确存在,那么就会省事一些。直接取出值在打印出即可。不用额外检查它是否真的存在。如果该键不存在,则会引发KeyError异常而被except子句捕捉到。

查看对象是否存在特定特性时:

obj.write

except AttributeError:

print 'The object is not writeable'

print 'The object is writeeable'

      本文转自潘阔 51CTO博客,原文链接:http://blog.51cto.com/pankuo/1661442,如需转载请自行联系原作者