一、什么是异常处理
定义:异常处理就是我们在写Python时,经常看到的报错信息,例如;NameError TypeError ValueError等,这些都是异常。
异常是一个事件,改事件会在程序执行过程中发生,影响程序的正常执行,一般情况下,在python中无法处理程序时就会发生异常,异常时Python的一个对象,表示一个错误,当Python脚本发生异常时,我们需要捕获并处理异常,否则程序就会终止执行。
二、异常处理
当Python脚本出现异常的时候我们怎么处理那?
就如我们使用的工具出现了一点毛病,我们可以想办法修理好它,程序也是一样,之前的前辈们经过不断的积累与思考,创造了很多好得方法处理程序中出现的异常,本章我们就讲一下使用try语句处理异常。
首先我们来说一下try语句的语法:
try语句与except 相结合使用,此语句用来检测try语句块中的错误,从而让except语句捕获异常信息并处理,如果不想在发生异常时结束程序,只需要在try语句中捕获异常即可
try: <代码块> except <异常名字> print(‘语句') 实例如下: def func(): try: a = x/y print('a=',a) return a eccept Exception: print('程序出现异常,异常信息:被除数为0')
三、抛出异常
在Python中使用raise语句抛出一个指定的异常,我们可以使用类或实例参数调用raise语句引发异常。
实例如下:
class EvaException(BaseException): def __init__(self,msg): self.msg=msg def __str__(self): return self.msg try: raise EvaException('类型错误') except EvaException as e: print(e)
四、捕捉多个异常
我们前面说了怎么处理一个异常的情况,如果涉及到多个,我们该怎么处理那?
在Python中支持一个try/except语句处理多个异常,语法如下:
try: <语句> except <异常名字>: print(‘异常说明') except <异常名字>: print(‘异常说明') try语句的工作方式如下: 首次执行try中语句块,如果没有发生异常,则忽略except中的字句,try语句中的代码块执行后结束。如果try语句中的代码块出现异常,try中的剩余语句则会被忽略, 如果异常和eccept中的异常名字一直,相应的except语句就会被执行。如果一个异常也没有匹配,这个异常就会传递给上层的try语句中,一个语句可能包含第一个except语句, 分别处理不同的异常,但是最多只有一个分支会执行。 try: #a #1/0 dic = {1:2} dic[3] except NameError: print('名字没有定义,报错了') except ZeroDivisionError: print('0不能当做除数,报错了') except KeyError: print('没有这个key')
五、异常中else
我们如果程序执行完异常后还想做其他的事情怎么办?
这时我们就可以用到异常中的else了,具体语法如下:
try: <语句> except <异常名字> : <语句> except <异常名字>: <语句> else: <语句> #(try语句中没有异常后执行此段代码) 如果在try语句中执行没有发生异常,就会执行else语句,使用else语句比把所有语句都放在try字句里面更好,这样可以避免一些意想不到的而except有没有捕获到的异常: def func(x,y): try: a = x/y except : print('Error,happened') else: print('It went as execpt') func(2,1)
六、用户自定义异常
你可以通过创建一个新的exception类来拥有自己的异常。异常应该继承自 Exception 类,或者直接继承,或者间接继承,例如:
class MyError(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) try: raise MyError(2*2) except MyError as e: print('My exception occurred, value:', e.value) My exception occurred, value: 4 raise MyError('oops!') Traceback (most recent call last): File "<stdin>", line 1, in ? main__.MyError: 'oops!' 在这个例子中,类 Exception 默认的 __init__() 被覆盖。 当创建一个模块有可能抛出多种不同的异常时,一种通常的做法是为这个包建立一个基础异常类,然后基于这个基础类为不同的错误情况创建不同的子类: class Error(Exception): """Base class for exceptions in this module.""" pass class InputError(Error): """Exception raised for errors in the input. Attributes: expression -- input expression in which the error occurred message -- explanation of the error """ def __init__(self, expression, message): self.expression = expression self.message = message class TransitionError(Error): """Raised when an operation attempts a state transition that's not allowed. Attributes: previous -- state at beginning of transition next -- attempted new state message -- explanation of why the specific transition is not allowed """ def __init__(self, previous, next, message): self.previous = previous self.next = next self.message = message 大多数的异常的名字都以"Error"结尾,就跟标准的异常命名一样。
七、定义清理行为(finally语句)
try 语句还有另外一个可选的子句,它定义了无论在任何情况下都会执行的清理行为。 例如:
>>> try: ... raise KeyboardInterrupt ... finally: ... print('Goodbye, world!') ... Goodbye, world! Traceback (most recent call last): File "<stdin>", line 2, in <module> KeyboardInterrupt 以上例子不管 try 子句里面有没有发生异常,finally 子句都会执行。 如果一个异常在 try 子句里(或者在 except 和 else 子句里)被抛出,而又没有任何的 except 把它截住,那么这个异常会在 finally 子句执行后再次被抛出。 下面是一个更加复杂的例子(在同一个 try 语句里包含 except 和 finally 子句): >>> def divide(x, y): try: result = x / y except ZeroDivisionError: print("division by zero!") else: print("result is", result) finally: print("executing finally clause") >>> divide(2, 1) result is 2.0 executing finally clause >>> divide(2, 0) division by zero! executing finally clause >>> divide("2", "1") executing finally clause Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 3, in divide TypeError: unsupported operand type(s) for /: 'str' and 'str' 预定义的清理行为 一些对象定义了标准的清理行为,无论系统是否成功的使用了它,一旦不需要它了,那么这个标准的清理行为就会执行。 这面这个例子展示了尝试打开一个文件,然后把内容打印到屏幕上: for line in open("myfile.txt"): print(line, end="") 以上这段代码的问题是,当执行完毕后,文件会保持打开状态,并没有被关闭。 关键词 with 语句就可以保证诸如文件之类的对象在使用完之后一定会正确的执行他的清理方法: with open("myfile.txt") as f: for line in f: print(line, end="") 以上这段代码执行完毕后,就算在处理过程中出问题了,文件 f 总是会关闭。
python标准异常
StopIteration