手把手教你用Python設(shè)計一個簡單的命令行界面

對 Python 程序來說火焰,完備的命令行界面可以提升團(tuán)隊的工作效率拆融,減少調(diào)用時可能碰到的困擾染突。今天淘太,我們就來教大家如何設(shè)計功能完整的 Python 命令行界面姻僧。

對 Python 開發(fā)者來說用的最多的界面恐怕還是命令行规丽。就拿我參與的機(jī)器學(xué)習(xí)項目來說,訓(xùn)練模型和評估算法的精確度都是通過在命令行界面運(yùn)行腳本來完成的段化。

所以調(diào)用一個 Python 腳本的時候我們希望這段腳本有一個盡量簡潔方便調(diào)用的接口嘁捷。尤其是團(tuán)隊中有多名開發(fā)者的時候這一點對提升團(tuán)隊的工作效率很重要。

要讓一段腳本方便調(diào)用總的來說有四個原則需要遵守:

  1. 提供默認(rèn)參數(shù)值
  2. 處理調(diào)用出錯的情況显熏,比如缺少參數(shù)雄嚣、參數(shù)類型錯誤或者找不到文件等
  3. 在文檔中說明各個參數(shù)和選項的用法
  4. 如果執(zhí)行時間較長應(yīng)該提供進(jìn)度條

一個簡單的例子

下面我們先通過一個簡單的例子來談?wù)勥@四個原則的具體應(yīng)用。例子中給出的腳本的功能是使用凱撒碼變換對文本進(jìn)行加密和解密喘蟆。

Caesar cipher:一種簡單的消息編碼方式缓升。在密碼學(xué)中,凱撒密碼蕴轨,移位密碼是最簡單和最廣為人知的加密技術(shù)之一港谊。

比如說我們想讓用戶通過命令行參數(shù)來選擇調(diào)用的方式是加密還是解密文本,而且用戶要從命令行傳入下面 encrypt 函數(shù)中的密匙參數(shù) key橙弱。

手把手教你用Python設(shè)計一個簡單的命令行界面

首先我們得在程序中拿到命令行參數(shù)歧寺。我在網(wǎng)上搜“ python 命令行參數(shù)”出來的第一個結(jié)果說讓我用 sys.argv ,那我們就來試試看它好不好用。

初級:笨辦法

其實 sys.argv 只是一個 list ,這個 list 的內(nèi)容是用戶調(diào)用腳本時所輸入的所有參數(shù)(其中也包括腳本的文件名)棘脐。

如果我像下面這樣調(diào)用加解密的腳本 caesar_script.py 的話:

> python caesar_script.py --key 23 --decrypt my secret message
pb vhfuhw phvvdjh

sys.argv 這個 list 的值就是:

['caesar_script.py', '--key', '23', '--decrypt', 'my', 'secret', 'message'] 

所以我們現(xiàn)在要遍歷這個 list 來找其中是否包括了“ –key ”或者“ -k ”斜筐,這樣我們就能找到密匙“ 23 ”。再找到“ –decrypt ”就能知道用戶是想要解密一段文本了(其實解密就是用密匙的相反數(shù)再加密一次)蛀缝。

完成后的代碼如下:

手把手教你用Python設(shè)計一個簡單的命令行界面

這段代碼基本上遵守了我們提到的四個原則:

  1. key 和 加密模式都設(shè)置了缺省參數(shù)
  2. 腳本可以處理像沒有文本或者缺少參數(shù)這樣比較基本的錯誤
  3. 用戶沒有給參數(shù)或者有錯的話會顯示使用幫助
> python caesar_script_using_sys_argv.py
Usage: python caesar.py [ --key <key> ] [ --encrypt|decrypt ] <text>

然而不算加密函數(shù)光處理參數(shù)我們就已經(jīng)寫了 39 行而且寫得一點也不優(yōu)雅顷链。我有膽說肯定還有更好的辦法來讀命令行參數(shù)。

中級:argparse

Python 標(biāo)準(zhǔn)庫里面提供了一個讀取命令行參數(shù)的庫——argparse 屈梁。我們來看看如果用 argparse 代碼怎么寫:

手把手教你用Python設(shè)計一個簡單的命令行界面

這樣寫也符合四項指導(dǎo)原則嗤练,而且對參數(shù)的說明和錯誤處理都優(yōu)于使用 sys.argv 的笨辦法:

手把手教你用Python設(shè)計一個簡單的命令行界面

不過我個人還是覺得代碼里第 7 行到第 13 行定義參數(shù)的部分寫得很啰嗦,而且我覺得參數(shù)應(yīng)該使用聲明式的方法來定義在讶。

高級: click

還有一個叫 click 的庫能實現(xiàn)我們想要的這些煞抬。它的基本功能和 argparse 是一樣的,但寫出來的代碼更優(yōu)雅真朗。

使用 click 改寫我們的加解密腳本之后是這樣的:

手把手教你用Python設(shè)計一個簡單的命令行界面

我們需要的參數(shù)和選項都用裝飾器來聲明此疹,這樣就可以在 caesar 函數(shù)里直接使用了。

上面的代碼里有幾點需要說明:

  1. nargs 參數(shù)是說這個參數(shù)的長度是幾個詞遮婶。默認(rèn)值是 1 不過用引號引起來的句子也只算一個詞蝗碎。這里我們設(shè)為 -1 是指不限制長度。
  2. --decrypt/--encrypt 這樣加一個斜杠的寫法用來指明互斥的選項旗扑,它的功能和 argparse 中的 add_mutually_exclusive_group 函數(shù)類似蹦骑。
  3. click.echo 是 click 提供的一個 print 功能,與 Python 2 和 3 都兼容臀防,而且有顏色高亮功能眠菇。

添加隱私功能

我們寫的是一個對文本加解密的腳本边败,但用戶卻直接把要加密的文本打出來了,這樣有別人用這個命令行的話按幾下上方向鍵就能看到我們的用戶加密了什么東西捎废,這是在是有點荒唐笑窜。

我們可以選擇把用戶要加密的文本隱藏起來,或者是從文件里讀文本登疗。這兩種方法都能解決我們的問題排截,但選擇權(quán)應(yīng)該留給用戶。

同理對于加解密的結(jié)果我們也讓用戶選擇是直接在命令行輸出還是保存成一個文件:

手把手教你用Python設(shè)計一個簡單的命令行界面

這里我給每個參數(shù)和選項都加上了一小段說明辐益,這樣我們的文檔能更清楚一點因為我們現(xiàn)在參數(shù)有點多了《习粒現(xiàn)在的文檔是這樣的:

手把手教你用Python設(shè)計一個簡單的命令行界面

兩個新的參數(shù) input_file 和 output_file 都是 click.File 類型,而且 click 幫我們處理了文件打開的讀寫方式和可能出現(xiàn)的錯誤智政,比如這樣:

手把手教你用Python設(shè)計一個簡單的命令行界面

如果用戶沒有提供 input_file 的話认罩,如說明文檔中所寫,則會讓用戶在命令行進(jìn)行輸入续捂,而且用戶輸入不再是明文了:

手把手教你用Python設(shè)計一個簡單的命令行界面

破譯密碼

假設(shè)我們現(xiàn)在是黑客垦垂,想解密但是不知道密匙該怎么辦呢?對凱撒加密的英文來說很容易牙瓢,只要調(diào)用解密函數(shù) 25 次然后看看那個結(jié)果不是亂碼就行了乔外。

要調(diào)用 25 次還要一個一個看還是太麻煩,其實只要數(shù)數(shù)哪個結(jié)果里正確的英文詞最多就行了一罩。下面我們就用 PyEnchant 來實現(xiàn)自動破譯密碼:

手把手教你用Python設(shè)計一個簡單的命令行界面

一氣呵成!

手把手教你用Python設(shè)計一個簡單的命令行界面

不過我們好像還沒有提到四項原則的最后一點:

4.如果執(zhí)行時間較長應(yīng)該提供進(jìn)度條

上面的腳本破譯 104 個詞的文本大約需要 5 秒撇簿∧粼ǎ考慮到要遍歷 25 個密匙還要數(shù)英文詞的個數(shù)這個時間并不算慢。

不過文本再長的話四瘫,比如 105 個詞的文本汉嗽,就要花 50 秒。這就有點長了找蜜,用戶可能沒有耐心等到程序運(yùn)行完就強(qiáng)退了饼暑。

所以我建議如果執(zhí)行時間長的話最好加上進(jìn)度條,關(guān)鍵是寫起來非常簡單:

手把手教你用Python設(shè)計一個簡單的命令行界面

不仔細(xì)看的話可能都看不出有什么區(qū)別洗做,因為區(qū)別只有四個字母 tqdm 弓叛,阿拉伯語中 tqdm 是進(jìn)度的意思。

tqdm 庫的用法非常簡單诚纸,只要把代碼中的迭代器用 tqdm 括起來就行了:

 for key in tqdm(range(26)):

這樣就會在命令行輸出一個進(jìn)度條撰筷,簡單得讓人不敢相信。

手把手教你用Python設(shè)計一個簡單的命令行界面

其實 click 的 click.progress_bar 也有類似的功能畦徘,但我覺得 click 的進(jìn)度條不好看而且寫法比tqdm 稍微麻煩一點毕籽。

總結(jié)一下希望大家讀完這篇文章能把設(shè)計 Python 命令行的這幾個原則用到實踐中去寫出更好用的 Python 命令行抬闯。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市关筒,隨后出現(xiàn)的幾起案子溶握,更是在濱河造成了極大的恐慌,老刑警劉巖蒸播,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件睡榆,死亡現(xiàn)場離奇詭異,居然都是意外死亡廉赔,警方通過查閱死者的電腦和手機(jī)肉微,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蜡塌,“玉大人碉纳,你說我怎么就攤上這事×蟀” “怎么了劳曹?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長琅摩。 經(jīng)常有香客問我铁孵,道長,這世上最難降的妖魔是什么房资? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任蜕劝,我火速辦了婚禮,結(jié)果婚禮上轰异,老公的妹妹穿的比我還像新娘岖沛。我一直安慰自己,他們只是感情好搭独,可當(dāng)我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布婴削。 她就那樣靜靜地躺著,像睡著了一般牙肝。 火紅的嫁衣襯著肌膚如雪唉俗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天配椭,我揣著相機(jī)與錄音虫溜,去河邊找鬼。 笑死股缸,一個胖子當(dāng)著我的面吹牛吼渡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播乓序,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼寺酪,長吁一口氣:“原來是場噩夢啊……” “哼坎背!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起寄雀,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤得滤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后盒犹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體懂更,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年急膀,在試婚紗的時候發(fā)現(xiàn)自己被綠了沮协。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡卓嫂,死狀恐怖慷暂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情晨雳,我是刑警寧澤行瑞,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站餐禁,受9級特大地震影響血久,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜帮非,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一氧吐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧末盔,春花似錦副砍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽角骤。三九已至隅忿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間邦尊,已是汗流浹背背桐。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留蝉揍,地道東北人链峭。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像又沾,于是被迫代替她去往敵國和親弊仪。 傳聞我的和親對象是個殘疾皇子熙卡,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 一、Python簡介和環(huán)境搭建以及pip的安裝 4課時實驗課主要內(nèi)容 【Python簡介】: Python 是一個...
    _小老虎_閱讀 5,753評論 0 10
  • 周二励饵,陰驳癌,夢涵六歲十一個月 昨晚夢涵發(fā)燒,我一直挺擔(dān)心的役听,不過早上起來沒有發(fā)燒挺精神的颓鲜,我送她去上學(xué),告訴她典予,如果...
    餃子的功力閱讀 279評論 0 0
  • 憶紅塵,醉紅顏孽椰。 這次只有最終效果圖了e_e抱歉抱歉 一開始想要錄視頻結(jié)果手機(jī)不給力昭娩,然后就沒有然后了,哈哈哈哈黍匾。...
    霧里in閱讀 918評論 35 41
  • 文/吳少如 這個世界上栏渺,如果不會有海鮮過敏癥狀的話,可能蝦是最受大眾歡迎的食物了锐涯。 蝦的品類上千種磕诊,那又怎樣呢?在...
    吳少如閱讀 514評論 0 4