求求你,別用 print 來(lái) debug 了
之前看過這個(gè)標(biāo)題的文章,看完后,我覺得太花里胡哨,用起來(lái)麻煩,我就用 print 來(lái) debug,沒毛病。
print 確實(shí)好用,因?yàn)樗銐蚝?jiǎn)單,簡(jiǎn)單到不需要思考,簡(jiǎn)單到任何一個(gè)程序員都可以使用任意的編程語(yǔ)言來(lái)打印一個(gè) hello world。
直到今天,我還是推薦 debug 時(shí)首選 print。
只不過,現(xiàn)在有了冰激凌,打印信息 debug 更甜了。
你說(shuō)冰激凌不是吃的嗎,怎么能 debug 了?
程序員 Ansgar Grunseid 看我們使用 print 即打印變量名稱,又打印變量的值,太辛苦啦,就做了一個(gè)工具,取名叫 icecream,讓打印信息 debug 這種方式更“甜”。
安裝:
pip install icecream
使用
from icecream import ic
下面把 icecream 簡(jiǎn)稱 ic。
打印變量時(shí) ic 的用法和 print 的用法基本一樣,但比 print 更好用:
ic 可以自動(dòng)打印變量或表達(dá)式的名稱。
ic 打印的結(jié)果更漂亮的,包含語(yǔ)法高亮。
ic 可以輸出程序的上下文:文件名,行號(hào),父函數(shù)名等信息。
ic 可以一次導(dǎo)入處處使用。
ic 可以配置前綴。
重要的是,它讓你編寫 print 語(yǔ)句的時(shí)間減少了 40%。
只要 print 不輸出到文件,不傳入 end 參數(shù),你可以在任何使用到 print 的地方替換為 ic,反之亦然。
你仍然可以不用 ic,但是如果經(jīng)常用 print 來(lái) debug,我就建議你用,為什么?
因?yàn)?print 是你的高頻要素,改善“高頻要素”會(huì)從根本上改善生命體的生活質(zhì)量。
ic 使用舉例:
檢查變量
#ice_demo.py
from icecream import ic
name = "Python七號(hào)"
ic(name)
def foo(i):
return i + 333
ic(foo(123))
d = {'key': {1: 'one'}}
ic(d['key'][1])
class klass():
attr = 'yep'
ic(klass.attr)
ic 的輸出很漂亮,自動(dòng)打印了變量或表達(dá)式的名稱,真的香,如下:

檢查執(zhí)行位置
不帶任何參數(shù)也是可以的:
from icecream import ic
expression = False
def foo():
ic()
#first()
if expression:
ic()
#second()
else:
ic()
#third()
foo()
ic 的輸出如下:
ic| demo.py:6 in foo() at 02:49:29.467
ic| demo.py:13 in foo() at 02:49:29.469
可以看出,ic() 還自動(dòng)輸出了時(shí)間戳,因此看程序執(zhí)行到哪里,直接調(diào)用 ic() 就完事。
ic 有返回值
ic 的返回值就是它參數(shù)的值:
In [1]: from icecream import ic
In [2]: a = 6
In [3]: b = ic(a)
ic| a: 6
In [4]: ic(b)
ic| b: 6
Out[4]: 6
如果你要返回 ic() 的輸出,可以這樣:
In [5]: out = ic.format(a)
In [6]: out
Out[6]: 'ic| a: 6'
一次導(dǎo)入處處使用
一個(gè)工程,會(huì)有很多 py 文件,不想在每個(gè)文件內(nèi)部都 import,可以這樣:
main.py 只導(dǎo)入一次
from icecream import install
install()
from xxx import foo
foo()
其他被 main 引用的文件 xxx.py 不需要再 import:
def foo():
x = 3
ic(x)
執(zhí)行 main.py 就會(huì)看到變量 x 的信息輸出。
這是因?yàn)椋琲nstall() 函數(shù)把 ic() 添加到了內(nèi)建模塊, 所有被編譯器打開的文件都會(huì)共享這個(gè) ic,當(dāng)然,可以通過 uninstall() 來(lái)卸載 ic。
靈活的前綴配置
In [1]: from icecream import ic
In [2]: ic.configureOutput(prefix='hello -> ')
In [3]: ic('world')
hello -> 'world'
Out[3]: 'world'
In [4]: import time
In [5]: def Timestamp():
...: return '%s |> ' % time.strftime("%Y-%m-%d %T")
...:
In [6]: ic.configureOutput(prefix=Timestamp)
In [7]: ic('world')
2021-04-01 11:02:20 |> 'world'
Out[7]: 'world'
configureOutput 還可以傳入 outputFunction、argToStringFunction、includeContext 參數(shù),這里你可以自己嘗試。
最后的話
請(qǐng)注意 icecream 是個(gè)通用的工具,不只是 Python 能用,以下編程語(yǔ)言也可以用:
Dart: icecream[1] Rust: icecream-rs[2] Node.js: node-icecream[3] C++: IceCream-Cpp[4] PHP: icecream-php[5] Go: icecream-go[6] Ruby: Ricecream[7] Java: icecream-java[8]
因此,很容易遷移到其他語(yǔ)言,如果你經(jīng)常用 print 來(lái) debug,現(xiàn)在是時(shí)候用 icecream 來(lái)提升下生活質(zhì)量了。如果你覺得有用,請(qǐng)分享、點(diǎn)贊、在看支持。
參考資料
icecream: https://github.com/HallerPatrick/icecream
[2]icecream-rs: https://github.com/ericchang00/icecream-rs
[3]node-icecream: https://github.com/jmerle/node-icecream
[4]IceCream-Cpp: https://github.com/renatoGarcia/icecream-cpp
[5]icecream-php: https://github.com/ntzm/icecream-php
[6]icecream-go: https://github.com/WAY29/icecream-go
[7]Ricecream: https://github.com/nodai2hITC/ricecream
[8]icecream-java: https://github.com/Akshay-Thakare/icecream-java
