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):
try:
return eval(expr)
except ZeroDivisionError:
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
>>>calculator.calc(‘10/0‘)
当计算器没有打开屏蔽机制时,ZeroDivisionError被捕捉但已传递了。
8.4 不止一个except 子句
try:
print 2/‘0‘
except ZeroDivisionError:
print ‘除数不能为0‘
except Exception:
print ‘其他类型异常‘
8.5 用一个块捕捉两个异常
如果需要用一个块捕捉多个异常,那么可以将它们作为元组列出:
try:
print 2/‘0‘
except (ZeroDivisionError,TypeError):
print ‘发生了一个异常‘
8.6 获取异常
try:
print 2/‘0‘
except (ZeroDivisionError,Exception) as e:
print e
在python3.0中,except子句会被写作except(ZerDivisionError,TypeError) as e.
8.7 捕捉所有异常
try:
print 2/‘0‘
except:
print ‘Something wrong happened。。‘
这样做是危险的,因为它会隐藏所有程序员未想到并且未做好准备处理的错误。
8.8 运用循环在异常
try:
print ‘A simple task‘
except:
print ‘What? Something went weong?‘
else:
print ‘Ah...It went as planned.‘
使用else子句:
while True:
try:
x = input(‘Enter the first number:‘)
y = input(‘Enter the second number:‘)
value = x/y
print ‘x/y is‘,value
except:
print ‘Invalid input,Please try again.‘
else:
break
这里的循环只在没有异常处理的情况下才会退出。换句话说,只要发生错误,程序会不断要求重新输入。
可以使用空的except子句来捕捉所有Exception类的异常(也会捕捉其所有子类的异常)。百分之百捕捉到所有的异常时不可能的,因为try/except语句中的代码可能会出问题,比如使用旧风格的字符串异常或自定义的异常类不是Exception类的子类。不过如果需要使用except Exception的话,可以使用打印的方法来显示错误信息:
while True:
try:
x = input(‘Enter the first number:‘)
y = input(‘Enter the second number:‘)
value = x/y
print ‘x/y is‘,value
except Exception,e:
print ‘Invalid input:‘,e
print ‘Please try again‘
else:
break
8.9 finally 子句
最后finally子句,它可以用来在可能的异常后进行清理。它和try子句联合使用:
x = None
try:
x = 1/0
finally:
print ‘Cleaning up...‘
del x
上面的代码中,finally子句肯定会被执行,不管子句try子句中是否发生异常。
使用del语句删除一个变量是非常不负责的清理手段,所以finally子句用于关闭文件或者网络套接字时会非常有用。还可以在同一条语句中组合使用try,except,finally和else。
try:
1/0
except NameError:
print "Unknown variable"
else:
print "That went well!"
finally:
print "Cleaning up."
8.10 异常和函数
如果异常在函数内引发而不被处理,它就会传播至函数调用的地方。如果在那里也没有处理异常,它就会继续传播,一直到达主程序(全局作用域)。如果那里没有异常处理程序,程序会带着堆栈跟踪中止:
>>>def faulty()
raise Exception(‘Something is wrong‘)
>>>def ignore_exception():
faulty()
>>>def handle_exception():
try:
faulty()
except:
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‘]
try:
print ‘Occupation:‘ + person[‘occupation‘]
except KeyError: pass
这里在打印职业时使用加号而不是逗号,否则字符串‘Occupation:‘在异常引发之前就会被输出。
这个程序直接假定‘occupation‘键存在。如果他的确存在,那么就会省事一些。直接取出值在打印出即可。不用额外检查它是否真的存在。如果该键不存在,则会引发KeyError异常而被except子句捕捉到。
查看对象是否存在特定特性时:
try:
obj.write
except AttributeError:
print ‘The object is not writeable‘
else:
print ‘The object is writeeable‘
本文出自 “linux_oracle” 博客,请务必保留此出处http://pankuo.blog.51cto.com/8651697/1661442
原文地址:http://pankuo.blog.51cto.com/8651697/1661442