Day 13 : 程序除错与异常

相信大家学到这边一定有碰过各式大大小小的程序错误,遇到程序出错很紧张怎麽办TAT。这里会衍生到时候我们将程序码上线,即时做过很多次的测试,还是有可能遇到非预期的错误。为了避免上线後的程序出错导致程序停止在非预期的地方,如何捕捉异常和异常处理是本节的重点!!

大致可以将错误分类成三种:

  • 语法错误:开发者不小心多一个括弧等等
  • 逻辑错误:可以执行成功但不是我们要的,例如银行存款金额是负数
  • 执行异常:在程序执行阶段所引发的错误

1. try except

发生了 ZeroDivisionError

def division(n1, n2):
    return  n1/n2
division(1, 0)

通常应该会做一些输入资料的检查来避免这种错误,但假设在爬网站,可能有各式各样的错误会发生。今天发现一个错误就要改一次程序码,明天发现错误又要改,那这支程序可能永远难以上线。为了避免这样的窘境,我们可以加上例外处理,让程序去捕捉我们没有想过的异常。另外也可以思考一个情境是提供程序给使用者,使用者可能会输入你没有想过的情境。如果因为他的输入导致你的程序异常,那使用者体验可能会很差。

def division(n1, n2):
    try:
        return  n1/n2
    except ZeroDivisionError:
        print("除数不可以为0")
division(1, 0)
>>> 除数不可以为0

有个调皮鬼输入文字,那怎麽办?

又发生错误了QQ

division('1', '0')

因此写 try except 想到的尽量加上去,最後再用 Exception 捡剩下的错误。

def division(n1, n2):
    try:
        return  n1/n2
    except ZeroDivisionError:
        print("除数不可以为0")
    except TypeError:
        print("请输入数字")
    except Exception as e
        print("错误资讯:", e)
division('1', '0')
>>> 请输入数字

2. try except else finally

刚刚上面介绍还并非完全型态呢XD
来来来这里是完全型态/images/emoticon/emoticon08.gif

try:
    # 尝试执行的程序码
except:
    # 当程序出现异常时执行的程序码
else:
    # 错误没有发生就会执行的程序码
finally:
    # 无论如何都要执行的程序码
def read_txt(file_path):
    try:
        with open(file_path) as file:
            data = file.read()
    except FileNotFoundError:
        print("路径异常:", file_path)
    else:
        print("成功了!")
    finally:
        print("感谢您使用本程序!")

3. 常见的例外错误

以下是常见的例外错误,大家可以自行参考,最後一个 Exception 代表通用型。

Type Name
Attribute 没有这个属性
FileNotFoundError 找不到档案
IOError 输入输出的错误
IndexError 索引超出范围
KeyError 没有该键
MemoryError 记忆体超出范围
NameError 未宣告该变数
SyntaxError 语法错误
SystemError 系统错误
TypeError 资料类别错误
ValueError 传入无效参数
ZeroDivisionError 除数为 0
Exception 可以代替错误的关键字

4. 丢出异常

有时候是我们想要检验逻辑是否错误,如果错误,就请程序停止不要再继续执行

此时该怎麽做呢? 可以使用 raise 关键字

def input_phone(number: str):
    if len(number) != 10:
        raise Exception('您的手机号码长度不正确')
    print('DONE')
    
input_phone('0912345678')
>>> DONE
input_phone('09123456789')

5. 自定义错误

若想要自己写例外的话,我们必须继承 Exception 物件。

若想让定义的物件像一般常见到的例外物件一样,能够直接透过物件实体来输出的话,须在物件中加入 __str__ 的物件方法。

class PasswordInputError(Exception):
    
    def __init__(self, password):
        self.password = password
        
    def __str__(self):
        return '错误讯息:' + self.password

print(e) 会调用 __str__ 的魔法方法,重写 Exception 原本写的方法。

password = input("请设定密码")
try:
    if len(password) < 5:
        raise PasswordInputError(password)
except Exception as e:
    print(e)

6. 断言

assert 是 raise 的一种特殊形式

assert 运算式, 参数

如果运算式是 False,并且内建的 __debug__为 True,则引发带有参数的 AssertError。

通常用於检查异常、写测试案例等等

save_money = input('请输入存款金额')
assert int(save_money) > 0 , '请输入大於零的数字'


<<:  Day-11: form_for 系虾密?很好用!

>>:  GNU Compiler Collection

Component 鬼牌(一): 看 props 决定 Component

鬼牌,在此借用的意思是「可以成为任何一张牌」 Dynamic Components 可以当鬼牌 Dy...

[Day25] Flutter - Application Authentication (part9)

前言 Hi, 我是鱼板伯爵接着就是来验证登入状态,如果已经登入就跳转到首页否则就在登入画面,看完我这...

09. E2E Test x Browser Test x Cypress

cypress 安装步骤 step 1. 安装 npm install cypress --save...

[Day 10] Checkbox 核取方块

在许多的输入中 很重要的核取方块 用於登入的勾选 ,资料的选取等等 利用 checked 判定核取状...

MyBatis 前导

MyBatis前导 ...