第十四章 异常处理及程序调试

1. 异常概述

在程序运行过程中,经常会遇到各种各样的错误,这些错误统称为“异常”。这些异常有的是由于开发者将关键字敲错导致的,这类错误多数产生的是 SyntaxError: invalid syntax(无效的语法),这将直接导致程序不能运行。这类异常是显式的,在开发阶段很容易被发现。还有一类是隐式的,通常和使用者的操作有关。例如,ZeroDivisionError(除数为0错误)的根源在于算术表达式“10/0”中,0作为除数出现,所以正在执行的程序被中断。

异常描述
NameError尝试访问一个没有声明的变量引发的错误
IndexError索引超出序列范围引发的错误
IndentationError缩进错误
ValueError传入的值错误
KeyError请求一个不存在的字典关键字引发的错误
IOError输入输出错误(如要读取的文件不存在)
ImportErrorimport语句无法找到模块或from无法在模块中找到相应的名称时引发的错误
AttributeError尝试访问未知的对象属性引发的错误
TypeError类型不合适引发的错误
MemoryError内存不足
ZeroDivisionError除数为0引发的错误

2. try…except 语句

在Python中,提供了try…except语句捕获并处理异常。在使用时,把可能产生异常的代码放在try语句块中,把处理结果放在except语句块中,这样,当try语句块中的代码出现错误时,就会执行except语句块中的代码,如果try语句块中的代码没有错误,那么except语句块将不会执行。具体的语法格式如下:

try:
    block1
except [ExceptionName [as alias]]:
    block2

参数说明:

  • block1:表示可能出现错误的代码块。

  • ExceptionName [as alias]:可选参数,用于指定要捕获的异常。其中,ExceptionName表示要捕获的异常名称,如果在其右侧加上as alias,则表示为当前的异常指定一个别名,通过该别名,可以记录异常的具体内容。

说明:在使用try…except语句捕获异常时,如果在except后面不指定异常名称,则表示捕获全部异常。

  • block2:表示进行异常处理的代码块。在这里可以输出固定的提示信息,也可以通过别名输出异常的具体内容。

说明:使用try…except语句捕获异常后,当程序出错时,输出错误信息后,程序会继续执行

def division():

    '''功能:分苹果'''

    print("\n===================== 分苹果了 =====================\n")
    apple = int(input("请输入苹果的个数:"))               	# 输入苹果的数量
    children = int(input("请输入来了几个小朋友:"))
    result = apple // children                            	# 计算每人分几个苹果
    remain = apple - result * children                    	# 计算余下几个苹果

    if remain > 0:
        print(apple, "个苹果,平均分给", children, "个小朋友,每人分", result, "个,剩下", remain, "个。")
    else:
        print(apple, "个苹果,平均分给", children, "个小朋友,每人分", result, "个。")

if __name__ == '__main__':
    try:                                               		# 捕获异常
        division()                                    		# 调用分苹果的函数
    except ZeroDivisionError:                         		# 处理异常
        print("\n出错了 ~_~ ――苹果不能被0个小朋友分!")
    except ValueError as e:                              	# 处理ValueError异常
        print("输入错误:", e)                            	# 输出错误原因

注意:在捕获异常时,如果需要同时处理多个异常也可以采用下面的代码实现:

try:                                                     	# 捕获异常
    division()                                            	# 调用分苹果的函数
except (ValueError,ZeroDivisionError ) as e:             	# 处理异常
print("出错了,原因是:",e)                            		# 显示出错原因

3. try…except…else 语句

在Python中,还有另一种异常处理结构,它是try…except…else语句,也就是在原来try…except语句的基础上再添加一个else子句,用于指定当try语句块中没有发现异常时要执行的语句块。该语句块中的内容当try语句中发现异常时,将不被执行。

def division():

    '''功能:分苹果'''

    print("\n===================== 分苹果了 =====================\n")
    apple = int(input("请输入苹果的个数:"))            		# 输入苹果的数量
    children = int(input("请输入来了几个小朋友:"))
    result = apple // children                         		# 计算每人分几个苹果
    remain = apple - result * children                   	# 计算余下几个苹果

    if remain > 0:
        print(apple, "个苹果,平均分给", children, "个小朋友,每人分", result, "个,剩下", remain, "个。")
    else:
        print(apple, "个苹果,平均分给", children, "个小朋友,每人分", result, "个。")

if __name__ == '__main__':
    try:                                                  	# 捕获异常
        division()                                        	# 调用分苹果的函数
    except ZeroDivisionError:                            	# 处理异常
        print("\n出错了 ~_~ ――苹果不能被0个小朋友分!")
    except ValueError as e:                              	# 处理ValueError异常
        print("输入错误:", e)                            	# 输出错误原因
    else:                                               	# 没有抛出异常时执行
        print("分苹果顺利完成...")

4. try…except…finally 语句

完整的异常处理语句应该包含finally代码块,通常情况下,无论程序中有无异常产生,finally代码块中的代码都会被执行,其语法格式如下:

try:
    block1
except [ExceptionName [as alias]]:
    block2
finally:
    block3

对于try…except…finally语句的理解并不复杂,它只是比try…except语句多了一个finally语句,如果程序中有一些在任何情形中都必须执行的代码,那么就可以将它们放在finally代码块中。

说明:使用except子句是为了允许处理异常。无论是否引发了异常,使用finally子句都可以执行清理代码。如果分配了有限的资源(如打开文件),则应将释放这些资源的代码放置在finally代码块中。

def division():

    '''功能:分苹果'''

    print("\n===================== 分苹果了 =====================\n")
    apple = int(input("请输入苹果的个数:"))            		# 输入苹果的数量
    children = int(input("请输入来了几个小朋友:"))
    result = apple // children                         		# 计算每人分几个苹果
    remain = apple - result * children                   	# 计算余下几个苹果

    if remain > 0:
        print(apple, "个苹果,平均分给", children, "个小朋友,每人分", result, "个,剩下", remain, "个。")
    else:
        print(apple, "个苹果,平均分给", children, "个小朋友,每人分", result, "个。")

if __name__ == '__main__':
    try:                                                	# 捕获异常
        division()                                  		# 调用分苹果的函数
    except ZeroDivisionError:                         		# 处理异常
        print("\n出错了 ~_~ ――苹果不能被0个小朋友分!")
    except ValueError as e:                             	# 处理ValueError异常
        print("输入错误:", e)                          		# 输出错误原因
    else:                                                	# 没有抛出异常时执行
        print("分苹果顺利完成...")
    finally:                                              	# 无论是否抛出异常都执行
        print("进行了一次分苹果操作。")

总结:
在这里插入图片描述

5. 使用 raise 语句抛出异常

如果某个函数或方法可能会产生异常,但不想在当前函数或方法中处理这个异常,则可以使用raise语句在函数或方法中抛出异常。raise语句的语法格式如下:

raise [ExceptionName[(reason)]]

其中,ExceptionName[(reason)]为可选参数,用于指定抛出的异常名称以及异常信息的相关描述。如果省略,就会把当前的错误原样抛出。

说明:ExceptionName(reason)参数中的“(reason)”也可以省略,如果省略,则在抛出异常时,不附带任何描述信息。

def division():

    '''功能:分苹果'''

    print("\n===================== 分苹果了 =====================\n")
    apple = int(input("请输入苹果的个数:"))           		# 输入苹果的数量
    children = int(input("请输入来了几个小朋友:"))

    if apple < children:
        raise ValueError("苹果太少了,不够分...")
    result = apple // children                       		# 计算每人分几个苹果
    remain = apple - result * children                  	# 计算余下几个苹果

    if remain > 0:
        print(apple, "个苹果,平均分给", children, "个小朋友,每人分", result, "个,剩下", remain, "个。")
    else:
        print(apple, "个苹果,平均分给", children, "个小朋友,每人分", result, "个。")

if __name__ == '__main__':
    try:                                           			# 捕获异常
        division()                                     		# 调用分苹果的函数
    except ZeroDivisionError:                             	# 处理ZeroDivisionError异常
        print("\n出错了 ~_~ ――苹果不能被0个小朋友分!")
    except ValueError as e:                            		# ValueError
        print("\n出错了 ~_~ ――",e)

6. 程序调试

在程序开发过程中,免不了会出现一些错误,有语法方面的,也有逻辑方面的。对于语法方面的比较好检测,因为程序会直接停止,并且给出错误提示。而对于逻辑错误就不太容易发现了,因为程序可能会一直执行下去,但结果是错误的。

Python提供了assert语句来调试程序。assert的中文意思是断言,它一般用于对程序某个时刻必须满足的条件进行验证。assert语句的基本语法如下:

assert expression [,reason]

参数说明:

  • expression:条件表达式,如果该表达式的值为真时,什么都不做,如果为假时,则抛出AssertionError异常。

  • reason:可选参数,用于对判断条件进行描述,为了以后更好地知道哪里出现了问题。

def division():

    '''功能:分苹果'''

    print("\n===================== 分苹果了 =====================\n")
    apple = int(input("请输入苹果的个数:"))        		# 输入苹果的数量
    children = int(input("请输入来了几个小朋友:"))
    assert apple > children ,"苹果不够分"           		# 应用断言调试
    result = apple // children                 			# 计算每人分几个苹果
    remain = apple - result * children         			# 计算余下几个苹果

    if remain > 0:
        print(apple, "个苹果,平均分给", children, "个小朋友,每人分", result, "个,剩下", remain, "个。")
    else:
        print(apple, "个苹果,平均分给", children, "个小朋友,每人分", result, "个。")

if __name__ == '__main__':
    division()                                			# 调用分苹果的函数

通常情况下,assert语句可以和异常处理语句结合使用。所以,可以将上面代码的最后一行代码修改为以下内容:

try:
    division()                                   		# 调用分苹果的函数
except AssertionError as e:                       		# 处理AssertionError异常
    print("\n输入有误:",e)

这样,再执行程序时就不会直接抛出异常(直接抛出异常指的是程序中断—红色字体)。

说明:assert语句只在调试阶段有效。我们可以通过在执行python命令时加入-O(大写)参数来关闭assert语句。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值