python入门07——错误、异常及异常处理

作为 Python 初学者,在刚学习 Python 编程时,经常会看到一些报错信息,这一章的笔记主要记录自己学习如何处理异常的过程。

Python 有两种错误很容易辨认:语法错误和异常。

一、语法错误

Python 的语法错误或者称之为解析错,是初学者经常碰到的。

my_list = ['zhai', 'zhang', 'yi', 'xing', 1007]
for index in my_list
    print(index)

上述代码由于for循环时忘记加冒号导致语法错误。系统会报错,语法分析器会指出出错的一行,并且在最先找到的错误的位置标记了一个小小的箭头。
在这里插入图片描述

二、异常

即便 Python 程序的语法是正确的,在运行它的时候,也有可能发生错误。运行期检测到的错误被称为异常。

异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行。
一般情况下,在Python无法正常处理程序时就会发生一个异常。
异常是Python对象,表示一个错误。

当Python脚本发生异常时我们需要捕获处理它,否则程序会终止执行。

python的标准异常如下所示。
在这里插入图片描述
更完整的异常请点击:@https://www.runoob.com/python/python-exceptions.html

较常见的异常如下所示:

1.AssertionError

my_list = [ ]
assert len(my_list) > 0

Python assert(断言)用于判断一个表达式,在表达式条件为 false 的时候触发异常。
在这里插入图片描述
2.AttributeError

my_list = [ ]
print(my_list.zhai)

该列表中没有zhai这个属性所以报错。
在这里插入图片描述
3.IndexError

my_list = [1, 2, 3]
print(my_list[3])

定义的列表下标范围为0、1、2,非法访问3。
在这里插入图片描述
4.KeyError

dic = {'one': 1, 'two': 2, 'three': 3}
print(dic['four'])  # 会报错
print(dic.get('four'))  # 不会报错

字典中没有key值为four的元素。
在这里插入图片描述
5.NameError

print(zhai)

访问了一个不存在的变量zhai。
在这里插入图片描述
6.TypeError

print(1 + 'zhai')

数字类型和字符串类型是不能直接相加的。
在这里插入图片描述

三、异常处理

捕捉异常可以使用try/except语句。
try/except语句用来检测try语句块中的错误,从而让except语句捕获异常信息并处理。

如果你不想在异常发生时结束你的程序,只需在try里捕获它。
以下为简单的try…except…else的语法:

try:
<语句>  #运行别的代码
except <名字><语句>  #如果在try部份引发了'name'异常
except <名字><数据>:
<语句>  #如果引发了'name'异常,获得附加的数据
else:
<语句>  #如果没有异常发生

try的工作原理是,当开始一个try语句后,python就在当前程序的上下文中作标记,这样当异常出现时就可以回到这里,try子句先执行,接下来会发生什么依赖于执行时是否出现异常。

  1. 如果当try后的语句执行时发生异常,python就跳回到try并执行第一个匹配该异常的except子句,异常处理完毕,控制流就通过整个try语句(除非在处理异常时又引发新的异常)。
  2. 如果在try后的语句里发生了异常,却没有匹配的except子句,异常将被递交到上层的try,或者到程序的最上层(这样将结束程序,并打印默认的出错信息)。
  3. 如果在try子句执行时没有发生异常,python将执行else语句后的语句(如果有else的话),然后控制流通过整个try语句。

【一个处理异常实例】

f = open('zhai.txt')  # 系统中不存在该文件
print(f.read())
f.close()

以上代码会出现FileNotFoundError的错误。所以我们需要用try…except来处理异常:

try:
    f = open('zhai.txt')
    print(f.read())
    f.close()
except OSError:  # python3将FileNotFoundError归为OSError
    print('文件出错啦/(ㄒoㄒ)/~~')
# 运行结果为文件出错啦/(ㄒoㄒ)/~~

对于程序员而言,我们更想要知道更多错误信息,那么我们就可以使用一个变量将错误原因传给该变量,如下所示:

try:
    f = open('zhai.txt')
    print(f.read())
    f.close()
except OSError as reason:
    print('文件出错啦/(ㄒoㄒ)/~~\n错误的原因是:' + str(reason))
# 运行结果为文件出错啦/(ㄒoㄒ)/~~
# 错误的原因是:[Errno 2] No such file or directory: 'zhai.txt'
1.使用except而不带任何异常类型

可以不带任何异常类型使用except,语法格式如下:

try:
    正常的操作
   ......................
except:
    发生异常,执行这块代码
   ......................
else:
    如果没有异常执行这块代码

以上方式try-except语句捕获所有发生的异常。但这不是一个很好的方式,我们不能通过该程序识别出具体的异常信息。因为它捕获所有的异常。(不推荐使用)

2.使用except而带多种异常类型

语法格式如下:

try:
    正常的操作
   ......................
except(Exception1[, Exception2[,...ExceptionN]]]):
   发生以上多个异常中的一个,执行这块代码
   ......................
else:
    如果没有异常执行这块代码

具体实现如下实例:

try:
    f = open('zhai.txt')
    print(f.read())
    f.close()
except (OSError, TypeError) as reason:  #发生这两个异常中的任意一个,执行这块代码
    print('出错啦/(ㄒoㄒ)/~~\n错误的原因是:' + str(reason))

也可以显示不同的异常类型的错误原因,如下所示:

try:
    sum(1 + '1')  # 该语句会出现TypeError 
    f = open('zhai.txt')  # 该语句会出现OSError 
    print(f.read())
    f.close()
except OSError as reason:
    print('文件出错啦/(ㄒoㄒ)/~~\n错误的原因是:' + str(reason))
except TypeError as reason:
    print('类型出错啦/(ㄒoㄒ)/~~\n错误的原因是:' + str(reason))
# 运行结果为类型出错啦/(ㄒoㄒ)/~~
# 错误的原因是:unsupported operand type(s) for +: 'int' and 'str'
3.try-finally 语句

try-finally 语句无论是否发生异常都将执行最后的代码。

语法格式为:

try:
<语句>
finally:
<语句>    #退出try时总会执行
raise

一个简单的实例:

try:
    f = open('zhai.txt', 'w')
    print(f.write("我存在了!"))
    sum = 1 + 'i'
    f.close()  # 执行到该步骤时刚写入文件中的数据才会保存
except (OSError, TypeError) as reason:
    print('出错啦/(ㄒoㄒ)/~~\n错误的原因是:' + str(reason))

print(open('zhai.txt', 'r').read())  # "我存在了!"并没有被成功写入该文件

运行结果为:
在这里插入图片描述

上述代码中可以看出写入文件中的数据并没有成功保存,是因为在 f.close() 前有一个TypeError类型的错误,从而程序会转去处理异常。为了避免这个问题,我们将 f.close() 这条必须要执行的语句放入finally代码块中,如下所示:

try:
    f = open('zhai.txt', 'w')
    print(f.write("我存在了!"))
    sum = 1 + 'i'
except (OSError, TypeError) as reason:
    print('出错啦/(ㄒoㄒ)/~~\n错误的原因是:' + str(reason))
finally:
    f.close()  # 成功保存

print(open('zhai.txt', 'r').read())  # "我存在了!"成功写入该文件

修正后的执行结果为:
在这里插入图片描述

四、raise触发异常

我们可以使用raise语句自己触发异常,raise语法格式如下:

raise [Exception [, args [, traceback]]]

一个异常可以是一个字符串,类或对象。 Python的内核提供的异常,大多数都是实例化的类,这是一个类的实例的参数。

print(1 / 0)  # 该语句会引发一个ZeroDivisionError的异常

我们也可以通过raise来引发ZeroDivisionError异常:

raise ZeroDivisionError

运行结果为:
在这里插入图片描述
也可以在引发异常时,输出信息:

raise ZeroDivisionError("此处为除数为零的异常!")

此时的运行结果为:
在这里插入图片描述
定义一个异常非常简单,如下所示:

def functionName( level ):
    if level < 1:
        raise Exception("Invalid level!", level)
        # 触发异常后,后面的代码就不会再执行

functionName(0)  # 此时满足level < 1

运行结果为:
在这里插入图片描述
为了能够捕获这个raise触发的异常,"except"语句必须有用相同的异常来抛出类对象或者字符串。

def functionName( level ):
    if level < 1:
        raise Exception("Invalid level!", level)
        # 触发异常后,后面的代码就不会再执行

try:
    functionName(0)            # 触发异常
except Exception as err:  # 使用相同的异常Exception
    print("这里是对raise触发异常的处理!")
else:
    print("其他异常!")
# 运行结果为:这里是对raise触发异常的处理!

五、用户自定义异常

通过创建一个新的异常类,程序可以命名它们自己的异常。异常应该是典型的继承自Exception类,通过直接或间接的方式。

以下为与RuntimeError相关的实例,实例中创建了一个类,基类为RuntimeError,用于在异常触发时输出更多的信息。

class Networkerror(RuntimeError):
    def __init__(self, arg):  # 构造器
        self.args = arg  # 输出为元组类型

在你定义以上类后,你可以触发该异常。在try语句块中,用户自定义的异常后执行except块语句,变量 e 是用于创建Networkerror类的实例。如下所示:

try:
    raise Networkerror("Bad hostname")
except Networkerror as e:
    print(e.args)

以上代码的运行结果为:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值