日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Day-10: 错误、调试和测试

發(fā)布時(shí)間:2024/1/17 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Day-10: 错误、调试和测试 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

  程序運(yùn)行時(shí),會(huì)遇到各種各樣的錯(cuò)誤。

  編寫(xiě)錯(cuò)誤叫做bug,而另一類(lèi)由于運(yùn)行過(guò)程中無(wú)法預(yù)測(cè)的,比如寫(xiě)文件時(shí),磁盤(pán)滿(mǎn)了,寫(xiě)不進(jìn)去;或者從網(wǎng)絡(luò)抓取數(shù)據(jù),網(wǎng)絡(luò)突然掉了。這些錯(cuò)誤稱(chēng)為異常,程序中需要對(duì)異常進(jìn)行處理,使得程序能夠運(yùn)行下去。

  • 錯(cuò)誤處理

  Python中,程序運(yùn)行錯(cuò)誤時(shí),如果錯(cuò)誤沒(méi)有捕獲,它會(huì)一直往上拋,最后被Python解釋器捕獲,打印一個(gè)錯(cuò)誤。

# err.py: def foo(s):return 10 / int(s)def bar(s):return foo(s) * 2def main():bar('0')main() $ python err.py Traceback (most recent call last):File "err.py", line 11, in <module>main()File "err.py", line 9, in mainbar('0')File "err.py", line 6, in barreturn foo(s) * 2File "err.py", line 3, in fooreturn 10 / int(s) ZeroDivisionError: integer division or modulo by zero

從上到下,錯(cuò)誤會(huì)一層層的反饋,直到顯示最終出錯(cuò)的地方。

  try...except...finally...:常用這種方法來(lái)檢查錯(cuò)誤并捕捉到,同時(shí)進(jìn)行相應(yīng)的處理。

try:print 'try...'r = 10 / 0print 'result:', r except ZeroDivisionError, e:print 'except:', e finally:print 'finally...' print 'END' try... except: integer division or modulo by zero finally... END

  注意到,錯(cuò)誤類(lèi)型有很多種,它們其實(shí)都是從BaseException類(lèi)派生出來(lái)的,常見(jiàn)的錯(cuò)誤類(lèi)型和繼承關(guān)系有:https://docs.python.org/2/library/exceptions.html#exception-hierarchy

  • 調(diào)試

  程序運(yùn)行一次就成功的概率很小,基本上不超過(guò)1%。一般有如下的調(diào)試方法:

  第一種,直接在可能出錯(cuò)的地方print出來(lái),但是后期會(huì)一個(gè)個(gè)刪掉。

  第二種,使用斷言來(lái)代替。

# err.py def foo(s):n = int(s)assert n != 0, 'n is zero!'return 10 / ndef main():foo('0')

斷言中,如果“n != 0”是錯(cuò)的,就拋出AssertionError,并顯示后面的字符串。

  第三種,使用logging。

  logging有debug,info,warning,error等幾個(gè)級(jí)別,從前到后優(yōu)先級(jí)依次提高,即如果,指定level=WARNING后,debug和info就不起作用了。這樣一樣,就可以輸出不同級(jí)別的信息,也不用刪除,最后統(tǒng)一控制輸出哪個(gè)級(jí)別的信息。

  logging的另一個(gè)好處是通過(guò)簡(jiǎn)單的配置,一條語(yǔ)句可以同時(shí)輸出到不同的地方,,比如console和文件。

# err.py import logging
logging.basicConfig(level=logging.INFO)s
= '0' n = int(s) logging.info('n = %d' % n) print 10 / n $ python err.py INFO:root:n = 0 Traceback (most recent call last):File "err.py", line 8, in <module>print 10 / n ZeroDivisionError: integer division or modulo by zero

  第四種調(diào)試方式,就是調(diào)試器pdb,讓程序以單步方式運(yùn)行,可以隨時(shí)查看運(yùn)行狀態(tài)。

# err.py s = '0' n = int(s) print 10 / n

然后,以參數(shù)-m pdb啟動(dòng),單步運(yùn)行

$ python -m pdb err.py > /Users/michael/Github/sicp/err.py(2)<module>() -> s = '0' (Pdb) l1 # err.py2 -> s = '0'3 n = int(s)4 print 10 / n [EOF]

輸入n單步運(yùn)行下一步

(Pdb) n > /Users/michael/Github/sicp/err.py(3)<module>() -> n = int(s) (Pdb) n > /Users/michael/Github/sicp/err.py(4)<module>() -> print 10 / n

輸入p 變量名來(lái)查看變量狀態(tài)。

(Pdb) p s '0' (Pdb) p n 0

輸入q結(jié)束運(yùn)行

(Pdb) n ZeroDivisionError: 'integer division or modulo by zero' > /Users/michael/Github/sicp/err.py(4)<module>() -> print 10 / n (Pdb) q

  另外在合適的地方,設(shè)置pdb.set_trace(),可以作為斷點(diǎn)。

# err.py import pdbs = '0' n = int(s) pdb.set_trace() # 運(yùn)行到這里會(huì)自動(dòng)暫停 print 10 / n $ python err.py > /Users/michael/Github/sicp/err.py(7)<module>() -> print 10 / n (Pdb) p n 0 (Pdb) c Traceback (most recent call last):File "err.py", line 7, in <module>print 10 / n ZeroDivisionError: integer division or modulo by zero

到達(dá)斷點(diǎn)時(shí),進(jìn)入pdb調(diào)試器。

  最后,還有方便的IDE調(diào)試器。

  • 單元測(cè)試

  單元測(cè)試,顧名思義,就是對(duì)一個(gè)部分測(cè)試,可以是一個(gè)模塊、一個(gè)函數(shù)或者一個(gè)類(lèi)。它的目的是保證該單元能夠?qū)崿F(xiàn)原先規(guī)劃的功能,為之后的整體調(diào)試做準(zhǔn)備。

  例如,現(xiàn)有模塊mydict.py,對(duì)它的要求是實(shí)現(xiàn)如下功能:

>>> d = Dict(a=1, b=2) >>> d['a'] 1 >>> d.a 1

mydict.py代碼如下:

class Dict(dict):def __init__(self, **kw):super(Dict, self).__init__(**kw)def __getattr__(self, key):try:return self[key]except KeyError:raise AttributeError(r"'Dict' object has no attribute '%s'" % key)def __setattr__(self, key, value):self[key] = value

編寫(xiě)的單元測(cè)試,需要引入unittest模塊,編寫(xiě)的mydict_test.py如下:

import unittestfrom mydict import Dictclass TestDict(unittest.TestCase):def test_init(self):  # 測(cè)試初始化功能d = Dict(a=1, b='test')self.assertEquals(d.a, 1)self.assertEquals(d.b, 'test')self.assertTrue(isinstance(d, dict))def test_key(self):  # 測(cè)試key的功能d = Dict()d['key'] = 'value'self.assertEquals(d.key, 'value')def test_attr(self):  # 測(cè)試屬性功能d = Dict()d.key = 'value'self.assertTrue('key' in d)self.assertEquals(d['key'], 'value')def test_keyerror(self):  # 測(cè)試key錯(cuò)誤的功能d = Dict()with self.assertRaises(KeyError):value = d['empty']def test_attrerror(self):  # 測(cè)試屬性錯(cuò)誤的功能d = Dict()with self.assertRaises(AttributeError):value = d.empty

  編寫(xiě)的單元測(cè)試類(lèi),從unittest.TestCase繼承。其中,只有以test開(kāi)頭的方法是測(cè)試方法。

  運(yùn)行單元測(cè)試時(shí),可以在測(cè)試文件中加入:

if __name__ == '__main__':unittest.main()

然后run。

  另一種,在命令行中輸入命令:

$ python -m unittest mydict_test ..... ---------------------------------------------------------------------- Ran 5 tests in 0.000sOK

第二種方法,可以一次運(yùn)行多個(gè)測(cè)試文件,比較方便。

  setUp與tearDown:在每個(gè)測(cè)試方法前后分別被執(zhí)行,避免在測(cè)試代碼中重復(fù)加入代碼。

  最后,單元測(cè)試要考慮到異常,代碼不能過(guò)于復(fù)雜,以免本身就有bug。

  • 文檔測(cè)試

  Python中可以提供實(shí)例文檔,在文件中編寫(xiě)特定格式的注釋,調(diào)用doctest判斷程序是否會(huì)像注釋中那樣的運(yùn)行。

class Dict(dict):'''Simple dict but also support access as x.y style.>>> d1 = Dict()>>> d1['x'] = 100>>> d1.x100>>> d1.y = 200>>> d1['y']200>>> d2 = Dict(a=1, b=2, c='3')>>> d2.c'3'>>> d2['empty']Traceback (most recent call last):...KeyError: 'empty'>>> d2.emptyTraceback (most recent call last):...AttributeError: 'Dict' object has no attribute 'empty''''def __init__(self, **kw):super(Dict, self).__init__(**kw)def __getattr__(self, key):try:return self[key]except KeyError:raise AttributeError(r"'Dict' object has no attribute '%s'" % key)def __setattr__(self, key, value):self[key] = valueif __name__=='__main__':import doctestdoctest.testmod()

然后run。如果什么都沒(méi)輸出,就說(shuō)明編寫(xiě)的doctest運(yùn)行都是正確的。

??注:本文為學(xué)習(xí)廖雪峰Python入門(mén)整理后的筆記

轉(zhuǎn)載于:https://www.cnblogs.com/likely-kan/p/7517924.html

總結(jié)

以上是生活随笔為你收集整理的Day-10: 错误、调试和测试的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。