<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          真叫人頭禿!Python也有pdb

          共 8503字,需瀏覽 18分鐘

           ·

          2020-11-18 00:15

          文 |?軒轅御龍

          來源:Python 技術(shù)「ID: pythonall」


          C有g(shù)db,Python也有pdb

          寫過C語言的同學(xué)們想必都很懷念(讀者:?)gdb調(diào)試器,使用gdb可以隨意在程序運(yùn)行過程中暫停流程、查看變量。

          很多時(shí)候,我們單純分析代碼流程和日志信息無法定位的問題,都得靠調(diào)試器來幫忙;可以說有了調(diào)試器,程序員才是代碼世界完整的上帝。

          Python當(dāng)然也不示弱,同樣存在這樣的巴別塔可以讓人升天

          01

          ——不過阿醬必須承認(rèn)的是,現(xiàn)代IDE集成的圖形化調(diào)試功能已經(jīng)很好使了,一般情況下使用命令行工具的場景并不多。

          但是也確實(shí)存在無法使用圖形化IDE的情況,因此對pdb工具略作了解還是很有必要的。畢竟誰也不知道可能被扔給一個(gè)什么樣的環(huán)境啊哈哈

          pdb的使用

          作為解釋型語言,Python調(diào)試工具的使用跟gdb畢竟還是有區(qū)別的。

          比如Python的調(diào)試就不需要什么符號表之類的東西,說到底,最終Python虛擬機(jī)執(zhí)行的邏輯也是自帶符號的。

          也正是由于Python的這種特殊性,所有pdb其實(shí)有兩種不太一樣的使用方式,即侵入式和非侵入式。

          其實(shí)按字面意思就很容易理解在兩種方式的使用。類比一下腦機(jī)接口,也分為侵入式和非侵入式。侵入式就表示要將電極、芯片植入大腦皮層,“侵入”人體;而非侵入式則是在頭骨外收集腦電波進(jìn)行分析。

          同樣地,侵入式pdb調(diào)用就是將調(diào)用pdb的代碼直接寫入Python腳本當(dāng)中;而非侵入式則是從命令行調(diào)用pdb,執(zhí)行相應(yīng)被調(diào)試腳本。

          1. 侵入式pdb

            使用方式如下代碼所示,在代碼中途插入一行調(diào)用:

            import?pdb;?#?pdb.set_trace()


            a?=?"just"
            b?=?"do"

            pdb.set_trace()

            c?=?['p',?'y',?'t',?'h',?'o',?'n']
            print(a)

            運(yùn)行腳本,會進(jìn)入這樣一個(gè)交互式界面:

            D:\000-GitHub\python-examples\xuanyuanyulong\2020-11-04-python-pdb>python?test_pdb_intrusive.py
            >?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py(21)()
            ->?c?=?['p',?'y',?'t',?'h',?'o',?'n']
            (Pdb)

            到這里已經(jīng)啟動了pdb,并且打印內(nèi)容中-> c = ['p', 'y', 't', 'h', 'o', 'n']行首的箭頭,表示當(dāng)前程序執(zhí)行流到了這一行代碼,如果繼續(xù)執(zhí)行,將首先執(zhí)行該行。

          2. 非侵入式pdb

            非侵入式要xue微簡單一些,最大的好處是不需要改動代碼。

            我們在控制臺執(zhí)行以下命令:

            D:\000-GitHub\python-examples\xuanyuanyulong\2020-11-04-python-pdb>python?-m?pdb?test_pdb_intrusive.py
            >?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py(1)()
            ->?import?pdb;?#?pdb.set_trace()
            (Pdb)

            可以看到,通過這種方式進(jìn)入調(diào)試,程序執(zhí)行流停在了程序開頭。

            通過分析進(jìn)入調(diào)試時(shí)代碼執(zhí)行流的位置,我們可以發(fā)現(xiàn),實(shí)際上侵入式的插入pdb.set_trace()調(diào)用,等價(jià)于我們從命令行啟動pdb,然后在這個(gè)調(diào)用的下一行打了一個(gè)斷點(diǎn),然后直接運(yùn)行程序。

          簡單命令

          gdb中有一些常用的簡單命令,本節(jié)阿醬帶大家熟悉一下,后續(xù)會做更深入的討論。

          1. h(elp)

            在pdb界面下輸入hhelp命令,即可列出pdb中支持的各種命令:

            (Pdb)?h

            Documented?commands?(type?help?):
            ========================================
            EOF????c??????????d????????h?????????list??????q????????rv???????undisplay
            a??????cl?????????debug????help??????ll????????quit?????s????????unt
            alias??clear??????disable??ignore????longlist??r????????source???until
            args???commands???display??interact??n?????????restart??step?????up
            b??????condition??down?????j?????????next??????return???tbreak???w
            break??cont???????enable???jump??????p?????????retval???u????????whatis
            bt?????continue???exit?????l?????????pp????????run??????unalias??where

            Miscellaneous?help?topics:
            ==========================
            exec??pdb

            在pdb后帶一個(gè)命令作為參數(shù),還可進(jìn)一步看到相應(yīng)的使用說明:

            (Pdb)?h?h
            h(elp)
            ????????Without?argument,?print?the?list?of?available?commands.
            ????????With?a?command?name?as?argument,?print?help?about?that?command.
            ????????"help?pdb"?shows?the?full?pdb?documentation.
            ????????"help?exec"?gives?help?on?the?!?command.

            相信我,help其實(shí)才是pdb里面最重要的命令。別的什么都可以記不住,但是help一定要記住。在以結(jié)果為導(dǎo)向的職場生活中也是一樣,遇到問題要及時(shí)求助喲~

          2. l(ist)

            打印當(dāng)前文件的源代碼。不帶參數(shù)的話,默認(rèn)打印當(dāng)前行前后共計(jì)11行代碼。繼續(xù)執(zhí)行該命令的話,則會繼續(xù)往后打印最多11行代碼,直到遇上文件結(jié)束符EOF。

            .作為參數(shù)則限定要強(qiáng)一點(diǎn),只會打印當(dāng)前行前后11行代碼。

            (Pdb)?l
            ??1??->?import?pdb;?#?pdb.set_trace()
            ??2
            ??3
            ??4?????def?addStr(a,?b):
            ??5?????????return?a?+?b
            ??6
            ??8?????????return?''.join(l)
            ??9
            ?10?????def?getSlogan(a,?b,?c):
            ?11?????????result?=?addStr(a,?b)?+?mergeChar(c)

            當(dāng)指定兩個(gè)參數(shù)時(shí),則打印這個(gè)區(qū)間內(nèi)的代碼:

            (Pdb)?l?3,?7
            ??3
            ??4?????def?addStr(a,?b):
            ??5?????????return?a?+?b
            ??6
            ??7??->?def?mergeChar(l:?list):

            而當(dāng)?shù)诙€(gè)參數(shù)b比第一個(gè)參數(shù)a小的時(shí)候,則表示“從第a行開始,繼續(xù)往后打印b行”,也就是總共打印(1+b)行:

            (Pdb)?l?7,?3
            ??7??->?def?mergeChar(l:?list):
            ??8?????????return?''.join(l)
            ??9
            ?10?????def?getSlogan(a,?b,?c):
          3. p/pp

            打印某個(gè)對象的值。區(qū)別在于pp調(diào)用的是pprint函數(shù),打印更加美觀。

            (Pdb)?p?a
            'just'
            (Pdb)?p?addStr

          4. !

            使用!可以在pdb環(huán)境下,執(zhí)行一般的Python語句。通常我們可以用來改變變量的值——要不怎么說調(diào)試器可以讓你成為上帝呢?還有比這更為所欲為的嗎?

            一般的話這個(gè)!其實(shí)可以省略,但是當(dāng)要執(zhí)行語句開頭的單詞與pdb的已有命令沖突,就得不到預(yù)期結(jié)果了,所以建議還是加上。

            這個(gè)用!領(lǐng)起命令的做法跟vim編輯器的邏輯很像,可以類比記憶。不熟悉的讀者可以忽略。

            (Pdb)?!a?=?"python"
            (Pdb)?p?a
            'python'
          5. r(eturn)

            pdb中,rreturn表示同一個(gè)意思,即“運(yùn)行當(dāng)前函數(shù)直到返回”。

            這一點(diǎn)上,r在pdb和gdb中的含義是不同的。讀者不必在意

          6. run/restart

            表示重新運(yùn)行當(dāng)前被調(diào)試程序。使用這個(gè)命令,可以為需要傳入?yún)?shù)的腳本傳入所需參數(shù)。

            格式與命令行執(zhí)行該腳本一樣,只是把相應(yīng)的python命令和腳本路徑替換為了runrestart。

            (Pdb)?run?a?b?c?d?kkk
            Restarting?test_pdb_intrusive.py?with?arguments:
            ????????test_pdb_intrusive.py
            >?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py(1)()
            ->?import?pdb;?#?pdb.set_trace()
            (Pdb)?!import?sys
            (Pdb)?p?sys.argv
            ['test_pdb_intrusive.py',?'a',?'b',?'c',?'d',?'kkk']
          7. b(reak)

            查看/添加斷點(diǎn)。

            不帶任何參數(shù)時(shí),即列出當(dāng)前已有斷點(diǎn)。

            (Pdb)?b?21
            Breakpoint?1?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21
            (Pdb)?b?17
            Breakpoint?2?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17
            (Pdb)?b
            Num?Type?????????Disp?Enb???Where
            1???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21
            2???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17

            同時(shí),通過runrestart重新運(yùn)行被調(diào)試程序,不會清除已有斷點(diǎn):

            (Pdb)?run
            Restarting?test_pdb_intrusive.py?with?arguments:
            ????????test_pdb_intrusive.py
            >?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py(1)()
            ->?import?pdb;?#?pdb.set_trace()
            (Pdb)?b
            Num?Type?????????Disp?Enb???Where
            1???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21
            2???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17
          8. cl(ear)

            有三種使用方式:1)類似設(shè)置斷點(diǎn)時(shí),清除特定文件特定行的斷點(diǎn);2)將要清除的斷點(diǎn)號列出來,以空格分隔;3)不帶參數(shù),清除所有斷點(diǎn)。

            下面一一演示:

            1)類似設(shè)置斷點(diǎn)時(shí),清除特定文件特定行的斷點(diǎn)

            (Pdb)?b
            Num?Type?????????Disp?Enb???Where
            1???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21
            2???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17
            (Pdb)?clear?test_pdb_intrusive.py:21
            (Pdb)?b
            Num?Type?????????Disp?Enb???Where
            2???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17

            2)將要清除的斷點(diǎn)號列出來,以空格分隔

            (Pdb)?b?21
            Breakpoint?3?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21
            (Pdb)?b?15
            Breakpoint?4?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15
            (Pdb)?b
            Num?Type?????????Disp?Enb???Where
            2???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17
            3???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21
            4???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15
            (Pdb)?clear?2?4
            Deleted?breakpoint?2?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17
            Deleted?breakpoint?4?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15
            (Pdb)?b
            Num?Type?????????Disp?Enb???Where
            3???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21

            3)不帶參數(shù),清除所有斷點(diǎn)

            (Pdb)?b?17
            Breakpoint?5?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17
            (Pdb)?b?15
            Breakpoint?6?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15
            (Pdb)?b
            Num?Type?????????Disp?Enb???Where
            3???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21
            5???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17
            6???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15
            (Pdb)?b
            Num?Type?????????Disp?Enb???Where
            3???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21
            5???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17
            6???breakpoint???keep?yes???at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15
            (Pdb)?clear
            Clear?all?breaks??yes
            Deleted?breakpoint?3?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21
            Deleted?breakpoint?5?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17
            Deleted?breakpoint?6?at?d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15
            (Pdb)?b

          好了打住打住,寫之前感覺pdb沒多少東西,沒想到寫起來才發(fā)現(xiàn),這么一點(diǎn)內(nèi)容就已經(jīng)這么多了,今天又熬夜了……

          02

          狗命要緊各位讀者老爺后會有期、后會有期

          總結(jié)

          pdb的內(nèi)容出乎意料地豐富,還有很多內(nèi)容在這篇文章中都沒能涉及。

          軟件調(diào)試其實(shí)也是一門很有趣的學(xué)問,當(dāng)然,也是一門很有用的學(xué)問


          由于微信平臺算法改版,公號內(nèi)容將不再以時(shí)間排序展示,如果大家想第一時(shí)間看到我們的推送,強(qiáng)烈建議星標(biāo)我們和給我們多點(diǎn)點(diǎn)【在看】。星標(biāo)具體步驟為:


          (1)點(diǎn)擊頁面最上方“小詹學(xué)Python”,進(jìn)入公眾號主頁。


          (2)點(diǎn)擊右上角的小點(diǎn)點(diǎn),在彈出頁面點(diǎn)擊“設(shè)為星標(biāo)”,就可以啦。


          感謝支持,比心。

          瀏覽 25
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  双飞少妇| 欧洲亚洲日本在线观看 | 欧美色图亚洲图片插菊花综合 | 欧美国产精品一区二区 | 国产精品 - 色哟哟 |