3.4.python_doctest, 自動測試模凷與try/except異常處理

環境:python 3.10_amd64 + Win10

1.doctest用法:

doctest是python自帶的測試模凷, 可根據文檔字符串內的語句進行簡單測試.

----代碼案例: 簡單測試----

import doctest  # 導入根據文檔字符串執行測試的模凷

def average(values):
    """計算數值列表的平均值
    >>> average([1,3,5,7])  # 函數調用
    4.0  # 預期結果
    """
    return sum(values)/len(values)


doctest.testmod()  # testmod()自動執行文檔字符串內的語句

"""這是文檔字符串""", 這樣的格式除了用于描述多行字符串常量之外, 也可用于類/函數的分行註釋, 一般稱作文檔字符串(docstring). 進行自動測試函數功能時, 首先得導入doctest模凷; 其次在文檔字符串內, 使用>>>提示符, 模擬python shell的格式, 注意>>>後一定要空一格, 然後輸入函數調用語句, 再換行輸入預期結果; 最後調用doctest.testmod()函數進行測試.

文檔內允許多項測試語句, 如:

...
>>> average([1,3,5,7])
4.0

>>> average([1,2,5,2])
2.5
...

如果預期結果等于return的返回值, 則通過測試, shell或終端啥也不會會輸出, 如下圖:

PS C:\Users\34513> & C:/Users/34513/.../python.exe c:/Users/.../main.py
PS C:\Users\34513> 

如果測試未通過(比如將上例的預期結果改爲2.0), 終端的輸出如下, 會指明具体行數的哪項測試未通過, 挺直白的:

**********************************************************************
File "C:\Users\34513\...\main.py", line 7, in __main__.average
Failed example:
    average([1,3,5,7])
Expected:
    2.0
Got:
    4.0
**********************************************************************
1 items had failures:
   1 of   1 in __main__.average
***Test Failed*** 1 failures.

1.1.報錯~~ValueError:... lacks blank after >>>: ...

ValueError: line 3 of the docstring for __main__.average lacks blank after >>>: '    >>>average([1,3,5,7])'

這个錯誤解釋的很直白, 就是文檔字符串中>>>後缺少了一个空格, 輸入時仔細點, 別漏了就是.

1.2.報錯~~AttributeError:

partially initialized module 'doctest' has no attribute 'testmod' (most likely due to a circular import)

大意是說, 部份初始化的模凷doctest沒有testmod屬性(可能是由于循環導入引起).導致這種錯誤的原因是因爲文件名與現有模凷名重復引起的(所以才叫循環/反復導入), import語句就近導入了一个不當命名的.py文件, 因此與現有模凷衝突.

本例中我是用doctest.py命名文件時觸發了這个錯誤, 只要重命名文件(比如tmp.py啊之類的無風險的名稱), 避免與現有模凷或python保留字重復即可.



2.try/except異常處理

2.1.try/except語法 

對于可預知的程序錯誤, 使用try/except語句可以在錯誤發生時執行特定動作, 避免程序崩潰.

----代碼實例: 當發生除數爲0的計算錯誤時發出提示

print("輸入兩个數, 我來計算它們的商.")
print("按'q'退出程序.")

while True:
    first_number = input("\nFirst number: ")
    if first_number == 'q':
        break
    second_number = input("Second number: ")
    if second_number == 'q':
        break
    try:
        answer = float(first_number) / float(second_number)
    except ZeroDivisionError:
        print('0不能用作除數!')
    else:
        print(answer)  # 在無異常時的行爲

----代碼實例: 讀取文件, 找不到文件時輸出錯誤信息:

def count_words(filename):
    """計算一个文本中包含的單詞數量"""
    try:
        with open(filename) as file_object:
            text_open = file_object.read()
    except FileNotFoundError:
        message = '無法找到文件!\n請檢查路徑或創建文件:' + filename
        print(message)
    else:
        words_list = text_open.split()  # split()方法將文本以單詞分割, 返回列表
        numbers = len(words_list)  # 計算全文的詞數
        return numbers

上面兩个例子說明了try/except的基本用法, 即預判可能發生的錯誤, 將python標準錯誤名寫在語句中, 並輸出友好的反饋信息.

2.2.多種異常的處理

1.針對不同的異常情況作不同處理(即執行不同的語句), 如:

try:
    # 待測試語句凷
except IOError:
    # 出現IO錯誤, 做點啥
except TypeError:
    # 出現類型錯誤, 做點啥

這樣比較細緻地處理了多種情況, 比如進行報錯時也更明瞭.

2.將多種可能的異常列爲元組, 統一處理

try:
    # 待測試語句凷
except (ValueError, TypeError, TypeError):
    # 對于以上多種異常, 做點啥

這樣好像只是節省了代碼量, 處理太籠統了.

3.統一處理所有異常

在try/except中, 不指定任何異常, 就是不管發生啥, 都統一處理, 籠統的程度更甚, 如:

# ...
try:
    print(x/y)
except:
    print('出錯!')

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值