转自:白月黑羽Python3教程之异常处理:http://www.python3.vip/doc/tutorial/python/0019/python
请你们运行以下代码git
a = 100/0 print(a)
就会发现解释器显示以下的错误提示函数
Traceback (most recent call last): File "xxxxxxxxxx.py", line 1, in <module> a = 100/0 ZeroDivisionError: division by zero
你们要学会看解释器的报错。编码
这就是解释器向咱们报告, 有一个 ZeroDivisionError 错误对象 或者说 异常对象 产生了。spa
这个 ZeroDivisionError 对象 表明的是一个除以0 的异常。 咱们知道0是不能做为除数的。命令行
由于这个问题,解释器没有办法继续执行后面的代码了。因此程序就此结束执行了。线程
ZeroDivisionError就是一个异常对象的类,继承自标准库里面的 Exception 类。code
Python标准库中还有不少其余的异常类 都是继承自标准库里面的 Exception 类,表明各类不一样类型的错误。orm
你们能够在命令行窗口 运行 Python 解释器交互命令行,分别输入以下代码:对象
xxxx
会产生 NameError,表示xxxx没有定义
dict1 = {1:1} print(dict1[2])
会产生 KeyError,表示该字典没有key为2的元素
import xxxx
会产生 ModuleNotFoundError,表示找不到xxxx这样的模块
解释器执行代码过程当中,若是发生异常,就会致使解释器无法继续按照正常流程往下执行代码,因此解释器会结束当前线程的执行。
若是执行的程序是个单线程的程序,整个程序执行就会结束了。
若是咱们在编码的时候,就预料到了某些代码运行时可能出现某些异常,就能够使用 try...except...
这样的方法来捕获和处理异常。
好比,咱们要开发程序,实现一个把用户输入的身高从英尺换算成米,以下所示
while True: miles = input('请输入英里数:') km = int(miles) * 1.609344 print(f'等于{km}千米')
编写这段代码的时候, 咱们就能够预料到,可能用户会输入非数字的字符,用int转化就会出错了,致使整个程序就退出了。
这时,咱们就能够这样写
while True: try: miles = input('请输入英里数:') km = int(miles) * 1.609344 print(f'等于{km}千米') except ValueError: print('你输入了非数字字符')
try 下面缩进的代码出现异常时,解释器会结束 try中 后续代码的执行,并检查这个异常的类型是否匹配后面的except 语句中声明的类型。
若是匹配上,就认为该异常是预先有对应的处理方案的,就执行匹配的except下面缩进的代码。从而不会结束当前线程。
上面的例子中,执行 try 下面缩进的代码时,若是用户输入了 hello
这样的非数字, 就会在这行语句处
km = int(miles) * 1.609344
产生 ValueError 类型的异常, 解释器就会去查看后面的 except 语句是否声明了对 ValueError 异常的处理。
发现有, 就会执行后面缩进的代码。也就是这句代码
print('你输入了非数字字符')
except 后面缩进的代码 就是对这种类型错误 的一种处理。
既然程序已经知道如何处理这种问题, 就不须要结束执行,只须要执行完 处理代码后, 进行原来正常的执行流程。
在这里,就是继续 while True
循环。
若是咱们开发程序的时候,估计某个代码段中可能出现好几种类型的异常,能够使用多个except 代码段,分别捕获多种类型的异常,以下
try: choice = input('输入你的选择:') if choice == '1': 100/0 elif choice == '2': [][2] except ZeroDivisionError: print ('出现 ZeroDivisionError') except IndexError : print ('出现 IndexError')
若是 输入’1’, 则会产生 ZeroDivisionError
异常, 就会被 except ZeroDivisionError
捕获,执行对应的代码
print ('出现 ZeroDivisionError')
若是 输入’2’, 则会产生 IndexError
异常, 就会被 except IndexError
捕获,执行对应的代码
print ('出现 IndexError')
咱们使用except 语句匹配异常类型的时候, 能够使用as关键字,后面加一个变量名,以下所示:
try: 100/0 except ZeroDivisionError as e: print (f'异常对象信息:{e}')
这样,运行代码的时候,当try中的语句产生异常对象时,就会 把产生的异常对象赋值给as后的变量。
上面的代码,运行输出
异常对象信息:division by zero
产生的异常对象赋值给了变量 e。
这样咱们就能够在后续的代码中获得产生的异常对象的信息。
若是咱们在写一段代码的时候,不知道这段代码会抛出什么样的异常,而且咱们不但愿程序由于异常而停止。
这时咱们能够匹配全部类型的异常,这样任何类型的异常发生都不会终止程序了。 以下:
try: 100/0 except Exception as e: print('未知异常:', e)
由于全部的异常都是 Exception
的子类。 因此 Exception能匹配全部类型的异常。
except 为空,也能够匹配全部类型的异常,并且能够经过traceback库,显示异常的信息和异常产生处的函数调用栈的信息,以下
import traceback try: 100/0 except : print(traceback.format_exc())
上面的代码会打印出致使异常的详细的函数调用栈的信息,以下
Traceback (most recent call last): File "xxxx/xxx.py", line 4, in <module> 100/0 ZeroDivisionError: division by zero
异常类型都是 继承自Exception的类,表示各类类型的错误。
咱们也能够本身定义异常,好比咱们写一个用户注册的函数, 要求用户输入的电话号码只能是中国的电话号码,而且电话号码中不能有非数字字符。
能够定义下面这两种异常类型:
# 异常对象,表明电话号码有错误的字符 class InvalidCharError(Exception): pass # 异常对象,表明电话号码非中国号码 class NotChinaTelError(Exception): pass
定义了上面的异常,当用户输入电话号码时,出现相应错误的时候,咱们就能够使用raise 关键字来抛出对应的自定义异常
def register(): tel = input('请注册您的电话号码:') # 若是有非数字字符 if not tel.isdigit(): raise InvalidCharError # 若是不是以86开头,则不是中国号码 if not tel.startswith('86'): raise NotChinaTelError return tel try: ret = register() except InvalidCharError: print('电话号码中有错误的字符') except NotChinaTelError: print('非中国手机号码')