python使用IPython調(diào)試debug程序
關(guān)于IPython使用的入門文章,主要介紹了如何在程序代碼中嵌入ipython用于調(diào)試,并分析了優(yōu)點(diǎn)與不足。
在 Python 中編程時(shí),我會(huì)花費(fèi)大量時(shí)間使用 IPython 及其強(qiáng)大的交互式提示,不僅用于一些一次性計(jì)算,還用于大量實(shí)際編程和調(diào)試。我特別將它用于一些探索性的編程,比如對(duì)一些不熟悉的 API,或者想知道程序在代碼中特定位置的運(yùn)行狀態(tài)。
我不確定這種IPython調(diào)試的方法有多普遍,但我很少聽到其他人談?wù)撍?,所以我認(rèn)為它值得分享。
安裝
使用前,需要將 IPython 安裝到您當(dāng)前的 virtualenv 中:
pip install ipython
使用方法
基本上有兩種方法可以打開 IPython 提示符。
第一種是直接從終端運(yùn)行它:
$ ipython Python 3.9.5 (default, Jul 1 2021, 11:45:58) Type 'copyright', 'credits' or 'license' for more information IPython 8.3.0 -- An enhanced Interactive Python. Type '?' for help. In [1]:
在 Django 項(xiàng)目中,如果您安裝了 IPython,也可以使用 ./manage.py shell
,好處是它會(huì)為幫您正確初始化 Django。
如果您想探索編寫一些“頂級(jí)”代碼,例如,在尚未創(chuàng)建入口點(diǎn)的情況下,編寫一個(gè)新的功能,那么這種方法很管用。然而,我寫的大部分代碼都不是這樣的。大多數(shù)時(shí)候,我發(fā)現(xiàn)自己需要寫代碼時(shí),已經(jīng)想好10層的函數(shù)調(diào)用了——比如:
- 我正在一個(gè)Django應(yīng)用程序中編寫一些視圖代碼,其中有一個(gè)請(qǐng)求對(duì)象--如果你在IPython提示符下從頭開始,你不可能輕易重新創(chuàng)建這個(gè)對(duì)象。
- 或者,模型層代碼,比如
save()
方法內(nèi)部的代碼,該方法本身正在被您尚未編寫的其他代碼調(diào)用,比如Django admin或某個(gè)信號(hào)。 - 或者,在一個(gè)測(cè)試中,設(shè)置代碼已經(jīng)創(chuàng)建了一大堆在打開IPython時(shí)不可用的東西。
對(duì)于這些情況,我使用第二種方法:
找到我想要修改、探索或調(diào)試的代碼。這通常是我自己的代碼,但也可能是第三方庫。我一直習(xí)慣在 virtualenv 中工作,所以即使使用第三方庫,在我的編輯器中“go to definition”也會(huì)直接將我?guī)У酱a的可寫副本的定義區(qū)(除了不是用 Python 編寫的代碼)。
插入 IPython 提示的代碼并保存文件:
import IPython; IPython.embed()
我將此綁定到編輯器中的一個(gè)功能鍵。
因此,如果它是Django視圖,那么代碼最終可能會(huì)是這樣:
def contact_us(request): if request.method == "POST": form = ContactUsForm_class(request.POST) if form.is_valid(): import IPython; IPython.embed() # …
以適當(dāng)?shù)姆绞接|發(fā)代碼。對(duì)于上述情況,首先需要在終端中運(yùn)行 Django 服務(wù)器,然后打開網(wǎng)頁,填寫表單并按下提交。對(duì)于測(cè)試,它將從終端運(yùn)行特定的測(cè)試。對(duì)于命令行應(yīng)用程序,它將直接運(yùn)行應(yīng)用程序。
在終端中,我會(huì)發(fā)現(xiàn)自己現(xiàn)在已經(jīng)在 IPython REPL 中,我可以繼續(xù):
- 想出我需要寫什么代碼
- 或者調(diào)試我感到困惑的代碼
請(qǐng)注意,您可以在此 REPL 中編寫和編輯多行代碼——它不像編輯器那么舒服,但沒關(guān)系,并且具有良好的歷史記錄支持。關(guān)于 IPython 及其更多特性,你可以在官方 文檔 中了解它。
對(duì)于那些有其他語言背景的人來說,可能還值得指出的是,Python REPL 與普通 Python 并沒有什么不同。你可以在普通 Python 中做的所有事情,比如定義函數(shù)和類,都可以在 REPL 中進(jìn)行。
調(diào)試結(jié)束后,我可以將任何有用的片段從 REPL 復(fù)制回我的真實(shí)代碼中,使用歷史記錄來查看我曾經(jīng)輸入的內(nèi)容。
優(yōu)點(diǎn)
這種方法的優(yōu)點(diǎn)是:
- 當(dāng)您實(shí)際擁有一個(gè)對(duì)象時(shí),您可以更輕松地探索API和對(duì)象(APIs and objects),而不是閱讀關(guān)于對(duì)象的文檔,或者編輯器的自動(dòng)完成工具推斷對(duì)象應(yīng)該具有的內(nèi)容。例如,Django的HttpRequest上有哪些屬性和方法?你不必確保你有正確的類型注釋,并且希望它們是完整的,或者假設(shè)值是什么——你已經(jīng)有了對(duì)象,你可以檢查它,用廣泛的合適的制表符自動(dòng)補(bǔ)全完成。你可以調(diào)用函數(shù),看看它們是怎么做的。
例如,Django的請(qǐng)求對(duì)象通常有一個(gè)用戶(user)屬性,該屬性不屬于HttpRequest定義的一部分,因?yàn)樗窃谝院筇砑拥?。但它在REPL中是可見的。 - 您可以直接探索程序的整體狀態(tài)。這對(duì)于探索性編程和調(diào)試來說都是一個(gè)巨大的優(yōu)勢(shì)。
對(duì)于調(diào)試,pdb 和類似的調(diào)試工具和環(huán)境通常會(huì)為您提供“the state of the system”,并且它們更擅長單步執(zhí)行多層代碼。但我經(jīng)常發(fā)現(xiàn) IPython 提示的功能和舒適性對(duì)于探索和尋找解決方案要好得多。
這種環(huán)境的感覺并不像Lisp中REPL驅(qū)動(dòng)的編程那樣流暢,但我仍然覺得它非常有趣和高效。與許多其他方法相比,比如迭代代碼,然后進(jìn)行手動(dòng)或自動(dòng)測(cè)試,它將反饋循環(huán)的延遲從幾秒或幾分鐘減少到幾毫秒,這是巨大的效率提升。
提示和不足
IPython 有很多很酷的特性可以在 REPL 環(huán)境中幫助你,比如 %autoreload 和許多其他很酷的魔法。你應(yīng)該花時(shí)間去了解他們!
在多線程(或多進(jìn)程)環(huán)境中,IPython 提示表現(xiàn)不是很好。如果可能的話,關(guān)閉多線程,或者確保你沒有遇到那個(gè)問題。
如果您確實(shí)在終端中搞砸了,您可能需要手動(dòng)找到要?dú)⑺赖倪M(jìn)程并在終端中進(jìn)行重置。
使用 Django 開發(fā)服務(wù)器:
- 它默認(rèn)是多線程的,所以要么確保你不會(huì)多次點(diǎn)擊視圖代碼,要么使用 --nothreading。
- 當(dāng)心自動(dòng)重新加載,如果你在啟動(dòng)時(shí)仍然處于 IPython 提示符中,它會(huì)搞砸你。要么使用 --noreload 要么確保在執(zhí)行任何會(huì)觸發(fā)重新加載的操作之前干凈地退出 IPython。
當(dāng)心捕獲標(biāo)準(zhǔn)輸入/輸出的環(huán)境,這會(huì)破壞這種功能。
pytest 默認(rèn)捕獲標(biāo)準(zhǔn)輸入并破壞一些事物。您可以使用 -s 將其關(guān)閉。此外,如果您使用的是 pytest-xdist,您應(yīng)該記得使用 -n0 來關(guān)閉多個(gè)進(jìn)程。
使用 IPython.embed() 時(shí),由于 Python 的限制,存在一個(gè)煩人的錯(cuò)誤,涉及閉包和未定義的名稱。它經(jīng)常在使用生成器表達(dá)式時(shí)出現(xiàn),但在其他時(shí)候也是如此。它通??梢酝ㄟ^以下方式解決:
globals().update(locals())
參考鏈接
以上就是python使用IPython調(diào)試debug程序的詳細(xì)內(nèi)容,更多關(guān)于IPython調(diào)試debug的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python3+requests接口自動(dòng)化session操作方法
今天小編就為大家分享一篇python3+requests接口自動(dòng)化session操作方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-10-10python中Switch/Case實(shí)現(xiàn)的示例代碼
本篇文章主要介紹了python中Switch/Case實(shí)現(xiàn)的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-11-11python使用selenium打開chrome瀏覽器時(shí)帶用戶登錄信息實(shí)現(xiàn)過程詳解
這篇文章主要介紹了python使用selenium打開chrome瀏覽器時(shí)帶用戶登錄信息,本文以實(shí)例給大家來展示如何讓selenium在打開chrome瀏覽器的時(shí)候帶上用戶的登錄信息,感興趣的朋友跟隨小編一起看看吧2022-02-02