第八篇 Python异常
在程序运行过程中,总会遇到各种各样的问题和错误。有些错误是我们编写代码时自己造成的,比如语法错误、调用错误,甚至逻辑错误。还有一些错误,则是不可预料的错误,但是完全有可能发生的,比如文件不存在、磁盘空间不足、网络堵塞、系统错误等等。这些导致程序在运行过程中出现异常中断和退出的错误,我们统称为异常。大多数的异常都不会被程序处理,而是以错误信息的形式展现出来。
异常有很多种类型,Python内置了几十种常见的异常,就在builtins模块内,无需特别导入,直接就可使用。需要注意的是,所有的异常都是异常类,首字母是大写的!
在发生异常的时候,Python会打印出异常信息,信息的前面部分显示了异常发生的上下文环境,并以调用栈的形式显示具体信息。异常类型作为信息的一部分也会被打印出来,例如ZeroDivisionError,NameError 和 TypeError。
1.1简单的捕获异常的语法
在程序开发中,如果对某些代码的执行不能确定是否正确,可以增加try来捕获异常:
1 try: 2 尝试执行的代码 3 except: 4 出现错误的处理
try…except…
语句处理异常的工作机制如下:
- 首先,执行try子句(在关键字try和关键字except之间的语句)
- 如果没有异常发生,忽略except子句,try子句执行后结束。
- 如果在执行try子句的过程中发生了异常,那么try子句余下的部分将被忽略。如果异常的类型和 except 之后的名称相符,那么对应的except子句将被执行。
1.2根据错误类型捕获异常
在程序执行时,可能会遇到不同类型的异常,可以针对不同的类型,做出不同的响应,此时就需要捕获错误类型。
1 try: 2 num = int(input("请输出整数:")) 3 result = (3 / num) 4 print(result) 5 except ZeroDivisionError: 6 print("除零错误") 7 except ValueError: 8 print("请输入正确的整数")
1.3捕获未知错误的异常
在开发时要预判所有可能出现的错误是有难度的,因此如果希望程序无论出现任何错误,都不会因为Python解释器抛出异常而终止,可以再增加一个except:Exception
1 try: 2 num = int(input("请输出整数:")) 3 result = (3 / num) 4 print(result) 5 except ZeroDivisionError: 6 print("除零错误") 7 except Exception as result: 8 print("未知错误 %s" %result)
说明:Exception可以捕获任意异常。
1.4异常捕获完整语法
1 try: 2 # 尝试执行的代码 3 pass 4 except 错误类型1: 5 # 针对错误类型1,对应的代码处理 6 pass 7 except (错误类型2,错误类型3): 8 # 针对错误类型2和错误类型3对应的代码处理 9 pass 10 except Exception as result: 11 # 打印错误信息 12 print(result) 13 else: 14 # 没有异常才会执行的代码 15 pass 16 finally: 17 # 无论是否有异常,都会执行的代码
18 pass
说明:else是一个可选的子句,必须放在所有except后面,这个子句将在try子句没有发生任何异常时执行。另外还有一个finally子句,表示无论try和except的子句执行情况,finally子句都会执行。
1.5异常的传递
异常的传递:当函数/方法执行出现异常时,会将异常传递给函数/方法的调用一方。如果传递到主程序,仍然没有异常处理,则程序会终止。
1 def demo01(): 2 return int(input("请输入一个整数:")) 3 4 5 def demo02(): 6 return demo01() 7 8 9 try: 10 print(demo02()) 11 except ValueError: 12 print("请输入正确的整数") 13 except Exception as result: 14 print("未知错误 %s" % result)
1.6抛出raise异常
在实际的开发中,除了代码执行出错Python解释器会抛出异常外,还可以根据业务需求,主动抛出异常。
在开发时,如果业务需求希望抛出异常,可以创建一个Exception的对象,然后使用raise关键字抛出异常对象。
1 def input_password(): 2 3 password = input("请输入密码:") 4 5 if len(password) > 8: 6 return password 7 8 exp = Exception("密码长度小于8位") 9 10 raise exp 11 12 13 try: 14 user_password = input_password() 15 print(user_password) 16 except Exception as result: 17 print("存在错误 %s" % result) 18 19 ------输出结果------ 20 请输入密码:123456 21 存在错误 密码长度小于8位
1.7自定义异常
Python内置了很多的异常类,并且这些类都是从BaseException类派生的。
下面是一些常见异常类,请把它们记下来!这样你在见到大多数异常的时候都能快速准确的判断异常类型。
异常名 | 解释 |
---|---|
AttributeError | 试图访问一个对象没有的属性 |
IOError | 输入/输出异常 |
ImportError | 无法引入模块或包;多是路径问题或名称错误 |
IndentationError | 缩进错误 |
IndexError | 下标索引错误 |
KeyError | 试图访问不存在的键 |
KeyboardInterrupt | Ctrl+C被按下,键盘终止输入 |
NameError | 使用未定义的变量 |
SyntaxError | 语法错误 |
TypeError | 传入对象的类型与要求的不符合 |
UnboundLocalError | 试图访问一个还未被设置的局部变量 |
ValueError | 传入一个调用者不期望的值,即使值的类型是正确的 |
OSError | 操作系统执行错误 |
大多数情况下,上面的内置异常已经够用了,但是有时候你还是需要自定义一些异常。自定义异常应该继承Exception
类,直接继承或者间接继承都可以,例如:
class MyExcept(Exception): def __init__(self, msg): self.message = msg def __str__(self): return self.message try: raise MyExcept('我的异常!') except MyExcept as ex: print(ex)
异常的名字都以Error
结尾,我们在为自定义异常命名的时候也需要遵守这一规范,就跟标准的异常命名一样。