异常类型 含义 SyntaxError 语法错误 AssertionError assert 后的条件为假时,程序停止运行抛出异常 AttributeError 当试图访问的对象属性不存在时抛出的异常 IndexError 索引超出序列范围会引发此异常 KeyError 字典中查找一个不存在的关键字时引发此异常 NameError 尝试访问一个未声明的变量时,引发此异常 TypeError 不同类型数据之间的无效操作 ZeroDivisionError 除法运算中除数为 0 引发此异常 IndentationError unexpected indents缩进异常 ValueError ArithmeticErro
( 1 ) try - except
try :
可能产生异常的代码块
except [ ( Error1, Error2, . . . ) [ as e] ] :
处理异常的代码块1
except [ ( Error3, Error4, . . . ) [ as e] ] :
处理异常的代码块2
except [ Exception] :
处理其它异常
1 、捕获异常:
首先执行 try 中的代码块,如果执行过程中出现异常,自动生成一个异常类型,
并将该异常提交给 Python 解释器
2 、处理异常:
Python 解释器收到异常对象时,寻找能处理该异常对象的 except 块,
如果找到合适的 except 块,则把该异常对象交给该 except 块处理
如果 Python 解释器找不到处理异常的 except 块,则程序运行终止,Python 解释器也退出
需要注意的是不管程序代码块是否处于 try 块中,甚至包括 except 块中的代码,
只要执行该代码块时出现了异常,系统都会自动生成对应类型的异常。
只是
如果此段程序没有用 try 包裹,又或者没有为该异常配置处理它的 except 块,
则 Python 解释器将无法处理,程序就会停止运行;
反之,如果程序发生的异常经 try 捕获并由 except 处理完成,则程序可以继续执行
( 2 ) try - except - else
else 中的代码块,只有当 try 块没有捕获到任何异常时,才会得到执行;
反之如果 try 块捕获到异常,即便调用对应的 except 处理完异常,else 块中的代码也不会得到执行
try :
result = 20 / int ( input ( '请输入除数:' ) )
print ( result)
except ValueError:
print ( '必须输入整数' )
except ArithmeticError:
print ( '算术错误,除数不能为 0' )
else :
print ( '没有出现异常' )
print ( "继续执行" )
运行结果:
请输入除数: 4
5.0
没有出现异常
继续执行
再次运行 运行结果:
请输入除数: a
必须输入整数
继续执行
try :
result = 20 / int ( input ( '请输入除数:' ) )
print ( result)
except ValueError:
print ( '必须输入整数' )
except ArithmeticError:
print ( '算术错误,除数不能为 0' )
print ( '没有出现异常' )
print ( "继续执行" )
运行结果:
请输入除数: a
必须输入整数
没有出现异常
继续执行
(3 )try - except - finally
无论 try 块是否发生异常,最终都要进入 finally 语句并执行其中的代码块
即便当 try 块发生异常且没有合适和 except 处理异常时,finally 块中的代码也会执行
和 else 语句必须和 try except 搭配使用 不同
finally 只要求和 try 搭配使用
而至于该结构中是否包含 except 以及 else ,对于 finally 不是必须的
当 try 块中的程序打开了一些物理资源(文件、数据库连接等)时
由于这些资源必须手动回收,而回收工作通常就放在 finally 块中
注意:
Python 垃圾回收机制,只能帮我们回收变量、类对象占用的内存
而无法自动完成类似关闭文件、数据库连接等这些的工作。
但是回收这些物理资源,也不是必须使用 finally ,但使用 finally 块是比较好的选择
因为:
首先,try 块不适合做资源回收,因为一旦 try 块中的某行代码发生异常,其后续代码将不会执行
其次,except 和 else 也不适合,它们都可能不会得到执行
而 finally 块中的代码,无论 try 块是否发生异常,finally 块中的代码也会执行
try :
a = int ( input ( "请输入 a 的值:" ) )
print ( 20 / a)
except :
print ( "发生异常!" )
else :
print ( "无错执行 else 块中的代码" )
finally :
print ( "执行 finally 块中的代码" )
请输入 a 的值: 4
5.0
无错执行 else 块中的代码
执行 finally 块中的代码
请输入 a 的值: a
发生异常!
执行 finally 块中的代码
try :
print ( 20 / 0 )
finally :
print ( "执行 finally 块中的代码" )
程序执行结果为:
执行 finally 块中的代码
Traceback ( most recent call last) :
File "D:\python3.6\1.py" , line 3 , in < module>
print ( 20 / 0 )
ZeroDivisionError: division by zero
( 4 ) 获取特定异常的有关信息
每种异常类型都提供了如下几个属性和方法,通过调用它们,就可以获取当前处理异常类型的相关信息:
args:返回异常的错误编号和描述字符串;
str ( e) :返回异常信息,但不包括异常信息的类型;
repr ( e) :返回较全的异常信息,包括异常信息的类型。
后面还可以了解到可以通过 traceback 模块获取异常信息
try :
1 / 0
except Exception as e:
print ( e. args)
print ( str ( e) )
print ( repr ( e) )
输出结果为:
( 'division by zero' , )
division by zero
ZeroDivisionError( 'division by zero' , )
一三两行输出是一个元组!因为一个except 可以处理多种异常
(5 )raise 在程序的指定位置手动抛出一个异常 手动抛出的异常并不会导致程序崩溃
基本语法格式为:
raise [ exceptionName [ ( reason) ] ]
raise :单独一个 raise 。
引发当前上下文中捕获的异常(比如在 except 块中)或默认引发 RuntimeError 异常。
raise 异常类名称:raise 后带一个异常类名称,表示引发执行类型的异常。
raise 异常类名称( 描述信息) :在引发指定类型的异常的同时,附带异常的描述信息。
try :
a = input ( "输入一个数:" )
if ( not a. isdigit( ) ) :
raise ValueError( "a 必须是数字" )
except ValueError as e:
print ( "引发异常:" , repr ( e) )
程序运行结果为:
输入一个数:a
引发异常: ValueError( 'a 必须是数字' , )
try 中raise 抛出ValueError异常,被try 捕获,在except 中处理该异常
当在没有引发过异常的程序使用无参的 raise 语句时,它默认引发的是 RuntimeError 异常。例如:
try :
a = input ( "输入一个数:" )
if ( not a. isdigit( ) ) :
raise
except RuntimeError as e:
print ( "引发异常:" , repr ( e) )
程序执行结果为:
输入一个数:a
引发异常: RuntimeError( 'No active exception to reraise' , )
(6 )有时只获得异常的类型是远远不够的,还需要借助更详细的异常信息才能解决问题
捕获异常时,有 2 种方式可获得更多的异常信息,分别是:
1 、使用 sys 模块中的 exc_info 方法;
将当前的异常信息以元组的形式返回,该元组中包含 3 个元素:
type :异常类型的名称,它是 BaseException 的子类
value:捕获到的异常实例
traceback:是一个 traceback 对象
对于第 3 个元素traceback 对象,无法直接看出有关异常的信息,还需要对其做进一步处理
要查看 traceback 对象包含的内容需要
调用 traceback 模块的 print_tb 方法
并将 sys. exc_info( ) 输出的 traceback 对象作为参数参入:
traceback. print_tb( sys. exc_info( ) [ 2 ] )
2 、使用 traceback 模块 查看异常的传播轨迹,追踪异常触发的源头, 参见本文最后的详细介绍
注意:
使用 sys、traceback 模块之前,都需要 import 引入
import sys
try :
x = int ( input ( "请输入一个被除数:" ) )
print ( "30除以" , x, "等于" , 30 / x)
except :
print ( sys. exc_info( ) )
print ( "其他异常..." )
当输入 0 时,程序运行结果为:
请输入一个被除数:0
( < class 'ZeroDivisionError' > ,
ZeroDivisionError( 'division by zero' , ) ,
< traceback object at 0x000001FCF638DD48 > )
其他异常. . .
import sys
import traceback
try :
x = int ( input ( "请输入一个被除数:" ) )
print ( "30除以" , x, "等于" , 30 / x)
except :
traceback. print_tb( sys. exc_info( ) [ 2 ] )
print ( "其他异常..." )
输入 0 ,程序运行结果为:
请输入一个被除数:0
File "C:\Users\mengma\Desktop\demo.py" , line 7 , in < module>
print ( "30除以" , x, "等于" , 30 / x)
其他异常. . .
输出信息中包含了更多的异常信息,包括文件名、抛出异常的代码所在的行数、抛出异常的具体代码。
( 7 ) traceback 查看异常的传播轨迹,追踪异常触发的源头。
class SelfException ( Exception) :
pass
def main ( ) :
firstMethod( )
def firstMethod ( ) :
secondMethod( )
def secondMethod ( ) :
thirdMethod( )
def thirdMethod ( ) :
raise SelfException( "自定义异常信息" )
main( )
运行结果
Traceback ( most recent call last) :
File "C:\Users\mengma\Desktop\1.py" , line 11 , in < module>
main( )
File "C:\Users\mengma\Desktop\1.py" , line 4 , in main < - - mian函数
firstMethod( )
File "C:\Users\mengma\Desktop\1.py" , line 6 , in firstMethod < - - 第三个
secondMethod( )
File "C:\Users\mengma\Desktop\1.py" , line 8 , in secondMethod < - - 第二个
thirdMethod( )
File "C:\Users\mengma\Desktop\1.py" , line 10 , in thirdMethod < - - 异常源头
raise SelfException( "自定义异常信息" )
SelfException: 自定义异常信息
会标明异常发生在哪个文件、哪一行、哪个函数处
异常的传播顺序与函数调用顺序相反,只要异常没有被完全捕获(包括异常没有被捕获,
或者异常被处理后重新引发了新异常),异常就从发生异常的函数或方法逐渐向外传播,
首先传给该函数或方法的调用者,该函数或方法的调用者再传给其调用者,
直至最后传到 Python 解释器,此时 Python 解释器会中止该程序,并打印异常的传播轨迹信息。
import traceback
class SelfException ( Exception) : pass
def main ( ) :
firstMethod( )
def firstMethod ( ) :
secondMethod( )
def secondMethod ( ) :
thirdMethod( )
def thirdMethod ( ) :
raise SelfException( "自定义异常信息" )
try :
main( )
except :
traceback. print_exc( )
traceback. print_exc( file = open ( 'log.txt' , 'a' ) )
traceback模块常用函数:
traceback. print_exc( ) :将异常传播轨迹信息输出到控制台或指定文件中。
format_exc( ) :将异常传播轨迹信息转换成字符串。
语法格式:print_exc( [ limit[ , file ] ] )
limit:用于限制显示异常传播的层数,比如函数 A 调用函数 B,函数 B 发生了异常,
如果指定 limit= 1 ,则只显示函数 A 里面发生的异常。如果不设置 limit 参数,则默认全部显示。
file :指定将异常传播轨迹信息输出到指定文件中。如果不指定该参数,则默认输出到控制台。