020、异常与警告
本文最后更新于 67 天前,其中的信息可能已经过时,如有错误请发送邮件到wuxianglongblog@163.com

异常与警告

异常

写代码的时候,出现错误必不可免。

看下面这段代码:

import math

while True:
    text = input('> ')
    if text[0] == 'q':
        break
    x = float(text)
    y = math.log10(x)
    print(f"log10({x}) = {y}")

这段代码接收命令行的输入,输入为数字时,计算它的对数并输出,直到输入值为 q 为止。

乍看没什么问题,然而输入0或者负数时:

import math

while True:
    text = input('> ')
    if text[0] == 'q':
        break
    x = float(text)
    y = math.log10(x)
    print(f"log10({x}) = {y}")
> -1

---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

Input In [1], in ()
      6     break
      7 x = float(text)
----> 8 y = math.log10(x)
      9 print(f"log10({x}) = {y}")

ValueError: math domain error

log10 函数会报错,因为不能接受非正值。

一旦报错,程序就会停止执行,如果不希望程序停止执行,那么可以添加一对 try & except:

import math

while True:
    try:
        text = input('> ')
        if text[0] == 'q':
            break
        x = float(text)
        y = math.log10(x)
        print(f"log10({x}) = {y}")
    except ValueError:
        print("the value must be greater than 0")
> -1
the value must be greater than 0
> 0
the value must be greater than 0
> 1
log10(1.0) = 0.0
> q

捕捉不同的异常类型

假设将这里的 y 更改为 1 / math.log10(x),此时输入 1:

import math

while True:
    try:
        text = input('> ')
        if text[0] == 'q':
            break
        x = float(text)
        y = 1 / math.log10(x)
        print(f"1 / log10({x}) = {y}")
    except ValueError:
        print("the value must be greater than 0")
> 1

---------------------------------------------------------------------------

ZeroDivisionError                         Traceback (most recent call last)

Input In [3], in ()
      7         break
      8     x = float(text)
----> 9     y = 1 / math.log10(x)
     10     print(f"1 / log10({x}) = {y}")
     11 except ValueError:

ZeroDivisionError: float division by zero

程序仍然抛出了异常,原因是ZeroDivisionError不在可处理的异常中。

可以有两种方法处理这个问题,第一种是捕获异常的父类Exception

import math

while True:
    try:
        text = input('> ')
        if text[0] == 'q':
            break
        x = float(text)
        y = 1 / math.log10(x)
        print(f"1 / log10({x}) = {y}")
    except Exception:
        print("invalid value")
> 1
invalid value
> 0
invalid value
> -1
invalid value
> q

第二种是指定多个错误类型:

import math

while True:
    try:
        text = input('> ')
        if text[0] == 'q':
            break
        x = float(text)
        y = 1 / math.log10(x)
        print(f"1 / log10({x}) = {y}")
    except (ZeroDivisionError, ValueError):
        print("invalid value")
> 1
invalid value
> 0
invalid value
> -1
invalid value
> q

还可以分开处理:

import math

while True:
    try:
        text = input('> ')
        if text[0] == 'q':
            break
        x = float(text)
        y = 1 / math.log10(x)
        print(f"1 / log10({x}) = {y}")
    except ValueError:
        print("the value must be greater than 0")
    except ZeroDivisionError:
        print("the value must not be 1")
> -1
the value must be greater than 0
> 1
the value must not be 1
> 2
1 / log10(2.0) = 3.321928094887362
> q

还可以将异常的具体信息打出来:

import math

while True:
    try:
        text = input('> ')
        if text[0] == 'q':
            break
        x = float(text)
        y = 1 / math.log10(x)
        print(f"1 / log10({x}) = {y}")
    except Exception as e:
        print(e)
> -1
math domain error
> 0
math domain error
> 1
float division by zero
> abcde
could not convert string to float: 'abcde'
> q

可以用raise主动抛出异常,例如判断月份是否在1-12之间:

month = 13

if not 1 <= month <= 12:
    raise ValueError(f"{month} must between 1 and 12!")
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

Input In [8], in ()
      1 month = 13
      3 if not 1 <= month <= 12:
----> 4     raise ValueError(f"{month} must between 1 and 12!")

ValueError: 13 must between 1 and 12!

finally

try/catch 块还有一个可选的关键词 finally。

不管 try 块有没有异常, finally 块的内容总是会被执行,而且会在抛出异常前执行,因此可以用来作为安全保证,比如确保打开的文件被关闭:

try:
    print(1)
finally:
    print('finally was called.')
1
finally was called.

如果有异常被抛出,finally的部分会在抛出异常前执行:

try:
    print(1 / 0)
finally:
    print('finally was called.')
finally was called.

---------------------------------------------------------------------------

ZeroDivisionError                         Traceback (most recent call last)

Input In [11], in ()
      1 try:
----> 2     print(1 / 0)
      3 finally:
      4     print('finally was called.')

ZeroDivisionError: division by zero

异常被处理了,则在最后执行:

try:
    print(1 / 0)
except Exception as e:
    print(e)
finally:
    print('finally was called.')
division by zero
finally was called.
谨此笔记,记录过往。凭君阅览,如能收益,莫大奢望。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇