错误与异常及处理
- 错误与异常
- 语法错误
- 异常
- 异常处理
- try...except...
- try...except...else...
- try...except...finally...
- raise
- 小结
- 附表
- Python 标准异常总结
哈喽,我们又见面啦~
到目前位置,我们见过许多错误信息,但我们只是对它有一个较为浅显的认识。在这一节中,我们将好好学习错误与异常,以及了解应该怎么去处理。
错误与异常
语法错误
语法错误又称解析错误,可能是我们学习Python中最容易遇到的错误了。例如,当我们编写如下代码时:
"""
语法错误
"""
if a<5
print(a)
运行程序后,我们得到下图的错误提示。原因是我们在编写if语句时,忘记在判断条件后添加:
,不符合python语法规范,因此解释器提示”SyntaxError“。
异常
即使语句或表达式在语法上是正确的,但在尝试执行的时候,程序仍有可能出现错误。在执行时检测到的错误被称为异常。还记得我们当初讲字符串时的索引越界吗?
"""
索引越界
"""
message="Hello world"
#得到字符串长度
mes_len=len(message)
print(mes_len) #11
#别忘是索引是从0开始的。
#虽然字符串的长度为mes_len,但可用的索引最大值为 (mes_len-1)
#故mes_len索引越界
print(message[mes_len])
在这段代码中,语句和表达式在语法上都是正确的,但当我们执行程序的时候,会显示出如下所示的异常信息。
错误信息的前一部分以堆栈的形式显示发生异常的上下文。通常它会列出发生错误的源代码的堆栈回溯(简单理解,就是一层一层地拨开,先是最表层的发生异常的代码的信息;若有进行函数调用,就继续返回函数调用内部的异常信息;直到找到最根源的异常为止)。
"""
堆栈回溯示例
"""
def div_zero(a):
"""将输入的值除以0"""
return a/0
def call_div_zero(a):
""""调用div_zero()"""
return div_zero(a)
#调用call_div_zero()
call_div_zero(4)
异常处理
try…except…
try语句的工作原理如下:
- 首先,执行try子句(try和except之间的语句)
- 若没有发生异常,则跳过except子句
- 若发生了异常,则跳过过该子句的剩下部分,跳转到except子句。若异常的类型和except后接的异常匹配,则执行对应的except子句,执行完后再跳转回未执行完的try子句中的代码段
- 若发生的异常和 except 子句中指定的异常不匹配,则将其传递到外部的 try 语句中。
"""
try...except...示例
"""
def get_number():
"""
输入被除数和除数
若产生数据类型转换错误,则处理
"""
while True:
a=input("input the first number: ")
b=input("input the second number: ")
try:
num1=int(a)
num2=int(b)
break
except ValueError:
print("please input numbers,try it again!\n")
return num1,num2
def div():
"""
进行除法操作
若产生除零异常,则处理
"""
while True:
try:
num1,num2=get_number()
result=num1/num2
print(f"the answer is {result}")
break
except ZeroDivisionError:
print("you can not divide by zero, try it again!\n")
div()
try…except…else…
同if语句相似,一个 try 语句可能有多个 except 子句,以指定不同异常的处理程序。
try … except 语句还有一个可选的 else 子句,在使用时必须放在所有的 except 子句后面。对于在try 子句不引发异常时必须执行的代码来说很有用。使用 else 子句比向 try 子句添加额外的代码要好,因为它避免了意外捕获由 try … except 语句保护的代码未引发的异常。
import sys
for arg in sys.argv[:]:
try:
f = open(arg, 'r')
except OSError:
print('cannot open', arg)
else:
print(arg, 'has', len(f.readlines()), 'lines')
f.close()
try…except…finally…
finally子句是try 语句中另一个可选子句,用于定义必须在所有情况下执行的清理操作。
如果存在 finally 子句,则 finally 子句将作为 try 语句结束前的最后一项任务被执行。 finally 子句不论 try 语句是否产生了异常都会被执行。 以下几点讨论了当异常发生时一些更复杂的情况:
- 如果在执行 try 子句期间发生了异常,该异常可由一个 except 子句进行处理。 如果异常没有被某个 except 子句所处理,则该异常会在 finally 子句执行之后被重新引发。
- 异常也可能在 except 或 else 子句执行期间发生。 同样地,该异常会在 finally 子句执行之后被重新引发。
- 如果在执行 try 语句时遇到一个 break, continue 或 return 语句,则 finally 子句将在执行 break, continue 或 return 语句之前被执行。
- 如果 finally 子句中包含一个 return 语句,则返回值将来自 finally 子句的某个 return 语句的返回值,而非来自 try 子句的 return 语句的返回值。
"""
如果 finally 子句中包含一个 return 语句
则返回值将来自 finally 子句的某个 return 语句的返回值
而非来自 try 子句的 return 语句的返回值。
"""
def bool_return():
try:
return True
finally:
return False
print(bool_return())
更复杂的情况
"""
finall更复杂的情况
"""
while True:
try:
x=input("input the first number: ")
y=input("input the second number: ")
result = int(x) / int(y)
except ZeroDivisionError:
print("division by zero!")
else:
print("result is", result)
finally:
print("executing finally clause\n")
raise
raise 语句允许程序员强制发生指定的异常。例如:
try:
raise NameError('HiThere') #抛出一个NameError异常
except NameError:
print('An exception flew by!')
小结
兜兜转转,也写了这么几天的博客了。也不知道屏幕前的你,是否有从中得到什么,无论好或不好,希望你能告诉我。
今天就这样吧,晚安!
附表
Python 标准异常总结
异常名 | 描述 |
BaseException | 所有异常的 基类 |
Exception | 常规异常的 基类 |
StandardError | 所有的内建标准异常的基类 |
ArithmeticError | 所有数值计算异常的基类 |
FloatingPointError | 浮点计算异常 |
OverflowError | 数值运算超出最大限制 |
ZeroDivisionError | 除数为零 |
AssertionError | 断言语句(assert)失败 |
AttributeError | 尝试访问未知的对象属性 |
EOFError | 没有内建输入,到达EOF标记 |
EnvironmentError | 操作系统异常的基类 |
IOError | 输入/输出操作失败 |
OSError | 操作系统产生的异常(例如打开一个不存在的文件) |
WindowsError | 系统调用失败 |
ImportError | 导入模块失败的时候 |
KeyboardInterrupt | 用户中断执行 |
LookupError | 无效数据查询的基类 |
IndexError | 索引超出序列的范围 |
KeyError | 字典中查找一个不存在的关键字 |
MemoryError | 内存溢出(可通过删除对象释放内存) |
NameError | 尝试访问一个不存在的变量 |
UnboundLocalError | 访问未初始化的本地变量 |
ReferenceError | 弱引用试图访问已经垃圾回收了的对象 |
RuntimeError | 一般的运行时异常 |
NotImplementedError | 尚未实现的方法 |
SyntaxError | 语法错误导致的异常 |
IndentationError | 缩进错误导致的异常 |
TabError | Tab和空格混用 |
SystemError | 一般的解释器系统异常 |
TypeError | 不同类型间的无效操作 |
ValueError | 传入无效的参数 |
UnicodeError | Unicode相关的异常 |
UnicodeDecodeError | Unicode解码时的异常 |
UnicodeEncodeError | Unicode编码错误导致的异常 |
UnicodeTranslateError | Unicode转换错误导致的异常 |
异常体系内部有层次关系,Python异常体系中的部分关系如下所示: