乐趣区

python错误、异常和程序调试

异常是 Python 程序在运行过程中引发的错误,如果程序中引发了未进行处理的异常,程序就会由于异常而终止运行,只有为程序添加异常处理,才能使程序更“健壮”。
Python 对异常的处理,有它自己的语法形式, 掌握如何在 Python 中处理异常和进行程序调试, 主要内容有:

列表项目
列表项目
语法错误;
异常的概念;
用 try 语句捕获异常;
常见异常的处理;
自定义异常;
使用 pdb 调试 Python 程序。

7.1 语法错误
1.拼写错误
即 Python 语言中的关键字写错,变量名、函数名拼写错误等。
关键字拼写错误时会提示 SyntaxError(语法错误),而变量名、函数名拼写错误会在运行时给出 NameError 的错误提示.
2.脚本程序不符合 Python 的语法规范
例如如少了括号,冒号等符号,以及表达式书写错误等。
3.缩进错误
因为 Python 语法规定,以缩进作为程序的语法之一,这应该是 Python 语言独特的一面。一般来说 Python 标准的缩进是以 4 个空格作为一个缩进。当然,你可以依据自己的习惯,使用 Tab 也可以。但同一个程序或项目中应该统一使用同一种缩进风格。
7.2 异常的处理
异常是 Python 程序在运行过程中引发的错误。如果程序中引发了未进行处理的异常,脚本就会由于异常而终止运行。只有在程序中捕获这些异常,并进行相关的处理,才能使程序不会中断运行。
7.2.1 异常处理的基本语法
Python 中使用 try 语句来处理异常,和 Python 中其他语句一样,try 语句也要使用缩进结构,try 语句也有一个可选的 else 语句块。一般的 try 语句基本形式如下。
try:
< 语句(块)> #可能产生异常的语句(块)
except < 异常名 1 >: #要处理的异常
< 语句(块)> #异常处理语句
except < 异常名 2 >: #要处理的异常
< 语句(块)> #异常处理语句
else:
< 语句(块)> #未触发异常,则执行该语句(块)
finally:
< 语句(块)> #始终执行该语,一般为了达到释放资源等目的

在实际应用中可以根据程序的需要而使用部分语句,常见的形式有:
形式一:
try:
< 语句(块)>
except < 异常名 1 >:
< 语句(块)>

举例:
def testTry (index, flag=False):
stulst = [“John”,”Jenny”,”Tom”]
if flag: #flag 为 True 时,捕获异常
try:
astu = stulst [index]
except IndexError:
print(“IndexError”)
return “Try Test Finished!”
else: #flag 为 False 时,不捕获异常
astu =stulst [index]
return “No Try Test Finished!”
print(“Right params testing start…”)
print (testTry (1, True)) #不越界参数,捕获异常(正常)
print (testTry (1, False)) #不越界参数,不捕获异常(正常)
print(“Error params testing start…”)
print (testTry (4, True)) #越界参数,捕获异常(正常)
print (testTry (4, False)) #越界参数,不捕获异常 (程序运行会中断)

形式二:
try:
< 语句(块)>
except < 异常名 1 >:
< 语句(块)>
finally:
< 语句(块)>

举例:
def testTryFinally (index):
stulst = [“John”,”Jenny”, “Tom”]
af = open (“my.txt”, ‘wt+’)
try:
af.write(stulst[index])
except:
pass
finally:
af.close() #无论是否产生越界异常,都关闭文件
print(“File already had been closed!”)
print(‘No IndexError…’)
testTryFinally (1) #无越界异常,正常关闭文件
print(‘IndexError…’)
testTryFinally (4) #有越界异常,正常关闭文件
7.2.2 Python 主要的内置异常及其处理
在 Python 中常见的异常都已经预定义好了,在交互式环境中,用 dir(__builtins__)命令,就会显示出所有的预定义异常。

异常名
描述

AttributeError
调用不存在的方法引发的异常

EOFError
遇到文件末尾引发的异常

ImportError
导入模块出错引发的异常

IndexError
列表越界引发的异常

IOError
I/ O 操作引发的异常,如打开文件出错等

KeyError
使用字典中不存在的关键字引发的异常

NameError
使用不存在的变量名引发的异常

TabError
语句块缩进不正确引发的异常

ValueError
搜索列表中不存在的值引发的异常

ZeroDivisionError
除数为零引发的异常

except 语句主要有以下几种用法:
except: #捕获所有异常;
except < 异常名 >: #捕获指定异常;
except(异常名 1,异常名 2): #捕获异常名 1 或者异常名 2;
except < 异常名 > as < 数据 >: #捕获指定异常及其附加的数据;
except(异常名 1,异常名 2)as < 数据 >:#捕获异常名 1 或者异常名 2 及异常的附加数据。
7.3 手工抛出异常
为了程序的需要,程序员还可以自定义新的异常类型,例如对用户输入文本的长度有要求,则可以使用 raise 引发异常,以确保文本输入的长度符合要求。
7.3.1 用 raise 手工抛出异常
使用 raise 引发异常十分简单,raise 有以下几种使用方式。
raise 异常名 raise 异常名,附加数据 raise 类名使用 raise 可以抛出各种预定的异常,即使程序在运行时根本不会引发该异常。
def testRaise2():
for i in range (5):
try:
if i==2: #i== 2 抛出 NameError 异常
raise NameError
except NameError:
print(‘Raise a NameError!’)
print (i)
print(‘end…’)

testRaise2 ()

运行结果:
0
1
Raise a NameError!
2
3
4
end…

7.3.2 assert 语句
assert 语句的一般形式如下。
assert < 条件测试 >, < 异常附加数据 > #其中异常附加数据是可选的

assert 语句是简化的 raise 语句,它引发异常的前提是其后面的条件测试为假。
举例:
def testAssert():
for i in range (3):
try:
assert i<2
except AssertionError:
print(‘Raise a AssertionError!’)
print (i)
print(‘end…’)

testAssert()
运行结果:
0
1
Raise a AssertionError!
2
end…

assert 语句一般用于在程序开发时测试代码的有效性。比如某个变量的值必须在一定范围内,而运行时得到的值不符合要求,则引发该异常,对开发者予以提示。所以一般在程序开发中,不去捕获这个异常,而是让它中断程序。原因是程序中已经出现了问题,不应继续运行。
assert 语句并不是总是运行的,只有 Python 内置的一个特殊变量__debug__为 True 时才运行。要关闭程序中的 assert 语句就使用 python-O(短画线,后接大写字母 O)来运行程序。
7.3.3 自定义异常类
在 Python 中定义异常类不用从基础完全自己定义,只要通过继承 Exception 类来创建自己的异常类。异常类的定义和其他类没有区别,最简单的自定义异常类甚至可以只继承 Exception 类,类体为 pass 如:
class MyError (Exception): #继承 Exception 类
pass

如果需要异常类带有一定的提示信息,也可以重载__init__和__str__这两个方法。

退出移动版