如何編寫(xiě)完美的 Python命令行程序?
這個(gè)版本有什么新東西嗎?
首先,注意到我給每個(gè)參數(shù)選項(xiàng)都加了個(gè)help參數(shù)。由于腳本變得復(fù)雜了,help參數(shù)可以給腳本的行為添加一些文檔。運(yùn)行結(jié)果如下:> python caesar_script_v2.py --h(huán)elpUsage: caesar_script_v2.py [OPTIONS]Options: --input_file FILENAME File in which there is the text you want to encrypt/decrypt. Ifnot provided, a prompt will allow you to type the input text. --output_file FILENAME File in which the encrypted/decrypted text will be written. Ifnot provided, the output text will just be printed. -d, --decrypt / -e, --encrypt Whether you want to encrypt the input textor decrypt it.-k, --keyINTEGER The numeric keyto use for the caesar encryption / decryption. --h(huán)elp Show this message andexit.
兩個(gè)新的參數(shù):input_file 和 output_file,類(lèi)型均為 click.File。該庫(kù)能夠用正確的模式打開(kāi)文件,處理可能的錯(cuò)誤,再執(zhí)行函數(shù)。例如:> python caesar_script_v2.py --decrypt --input_file wrong_file.txtUsage: caesar_script_v2.py [OPTIONS]Error: Invalid value for"--input_file": Could notopen file: wrong_file.txt: No such file or directory
正像help文本中解釋的那樣,如果沒(méi)有提供input_file,就使用click.promp讓用戶(hù)直接在提示符下輸入文本,在加密模式下這些文本是隱藏的。如下所示:> python caesar_script_v2.py --encrypt --key 2Enter a text: **************yyy.ukectc.eqo
破解密文!
現(xiàn)在設(shè)想你是個(gè)黑客:你要解密一個(gè)用凱撒加密過(guò)的密文,但你不知道秘鑰是什么。
最簡(jiǎn)單的策略就是用所有可能的秘鑰調(diào)用解密函數(shù) 25 次,閱讀解密結(jié)果,看看哪個(gè)是合理的。
但你很聰明,而且也很懶,所以你想讓整個(gè)過(guò)程自動(dòng)化。確定解密后的 25 個(gè)文本哪個(gè)最可能是原始文本的方法之一,就是統(tǒng)計(jì)所有這些文本中的英文單詞的個(gè)數(shù)。這可以使用 PyEnchant 模塊實(shí)現(xiàn):
import clickimport enchantfrom caesar_encryption import encrypt@click.command()@click.option('--input_file', type=click.File('r'),required=True,)@click.option('--output_file', type=click.File('w'),required=True,)defcaesar_breaker(input_file, output_file): cyphertext = input_file.read() english_dictionnary = enchant.Dict("en_US")max_number_of_english_words = 0for key in range(26): plaintext = encrypt(cyphertext, -key) number_of_english_words = 0for word in plaintext.split(' '):if word and english_dictionnary.check(word):number_of_english_words += 1if number_of_english_words > max_number_of_english_words: max_number_of_english_words = number_of_english_words best_plaintext = plaintext best_key = keyclick.echo(f'The most likely encryption key is {best_key}. It gives the following plaintext:\n\n{best_plaintext[:1000]}...')output_file.write(best_plaintext)if __name__ == '__main__':caesar_breaker()
貌似運(yùn)行得很不錯(cuò),但別忘了,好的命令行程序還有個(gè)規(guī)則需要遵守:
4.A 不是立即完成的任務(wù)應(yīng)當(dāng)顯示進(jìn)度條。
示例中的文本包含10^4個(gè)單詞,因此該腳本需要大約5秒才能解密。這很正常,因?yàn)樗枰獧z查所有25個(gè)秘鑰,每個(gè)秘鑰都要檢查10^4個(gè)單詞是否出現(xiàn)在英文字典中。
假設(shè)你要解密的文本包括10^5個(gè)但I(xiàn)C,那么就要花費(fèi)50秒才能輸出結(jié)果,用戶(hù)可能會(huì)非常著急。
因此我建議這種任務(wù)一定要顯示進(jìn)度條。特別是,顯示進(jìn)度條還非常容易實(shí)現(xiàn)。
下面是個(gè)顯示進(jìn)度條的例子:
import clickimport enchantfrom tqdm import tqdmfrom caesar_encryption import encrypt@click.command()@click.option('--input_file',type=click.File('r'), required=True,)@click.option('--output_file',type=click.File('w'), required=True,)defcaesar_breaker(input_file, output_file): cyphertext = input_file.read() english_dictionnary = enchant.Dict("en_US") best_number_of_english_words = 0for key in tqdm(range(26)): plaintext = encrypt(cyphertext, -key)number_of_english_words = 0for word in plaintext.split(' '):if word and english_dictionnary.check(word): number_of_english_words += 1if number_of_english_words > best_number_of_english_words:best_number_of_english_words = number_of_english_words best_plaintext = plaintext best_key = key click.echo(f'The most likely encryption key is {best_key}. It gives the following plaintext:\n\n{best_plaintext[:1000]}...')output_file.write(best_plaintext)if __name__ == '__main__':caesar_breaker()
你發(fā)現(xiàn)區(qū)別了嗎?可能不太好找,因?yàn)閰^(qū)別真的很小,只有四個(gè)字母:tqdm。
tqdm 是 Python 庫(kù)的名字,也是它包含的類(lèi)的名字。只需用它包裹一個(gè)可迭代的東西,就能顯示出進(jìn)度條:
forkeyin tqdm(range(26)):
這樣就能顯示出非常漂亮的進(jìn)度條。我都不敢相信這是真的。
另外,click也提供類(lèi)似的顯示進(jìn)度條的工具(click.progress_bar),但我覺(jué)得它的外觀不太容易懂,而且要寫(xiě)的代碼也多一些。
我希望這篇文章能讓你在改進(jìn)開(kāi)發(fā)者的體驗(yàn)上多花點(diǎn)時(shí)間。

發(fā)表評(píng)論
登錄
手機(jī)
驗(yàn)證碼
立即登錄即可訪(fǎng)問(wèn)所有OFweek服務(wù)
還不是會(huì)員?免費(fèi)注冊(cè)
忘記密碼請(qǐng)輸入評(píng)論內(nèi)容...
請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字
圖片新聞
-
機(jī)器人奧運(yùn)會(huì)戰(zhàn)報(bào):宇樹(shù)機(jī)器人摘下首金,天工Ultra搶走首位“百米飛人”
-
存儲(chǔ)圈掐架!江波龍起訴佰維,索賠121萬(wàn)
-
長(zhǎng)安汽車(chē)母公司突然更名:從“中國(guó)長(zhǎng)安”到“辰致科技”
-
豆包前負(fù)責(zé)人喬木出軌BP后續(xù):均被辭退
-
字節(jié)AI Lab負(fù)責(zé)人李航卸任后返聘,Seed進(jìn)入調(diào)整期
-
員工持股爆雷?廣汽埃安緊急回應(yīng)
-
中國(guó)“智造”背后的「關(guān)鍵力量」
-
小米汽車(chē)研發(fā)中心重磅落地,寶馬家門(mén)口“搶人”
最新活動(dòng)更多
-
即日-9.16點(diǎn)擊進(jìn)入 >> 【限時(shí)福利】TE 2025國(guó)際物聯(lián)網(wǎng)展·深圳站
-
10月23日火熱報(bào)名中>> 2025是德科技創(chuàng)新技術(shù)峰會(huì)
-
10月23日立即報(bào)名>> Works With 開(kāi)發(fā)者大會(huì)深圳站
-
10月24日立即參評(píng)>> 【評(píng)選】維科杯·OFweek 2025(第十屆)物聯(lián)網(wǎng)行業(yè)年度評(píng)選
-
11月27日立即報(bào)名>> 【工程師系列】汽車(chē)電子技術(shù)在線(xiàn)大會(huì)
-
12月18日立即報(bào)名>> 【線(xiàn)下會(huì)議】OFweek 2025(第十屆)物聯(lián)網(wǎng)產(chǎn)業(yè)大會(huì)
推薦專(zhuān)題
-
10 甲骨文大漲,算力瘋狂
- 1 先進(jìn)算力新選擇 | 2025華為算力場(chǎng)景發(fā)布會(huì)暨北京xPN伙伴大會(huì)成功舉辦
- 2 人形機(jī)器人,正狂奔在批量交付的曠野
- 3 宇樹(shù)機(jī)器人撞人事件的深度剖析:六維力傳感器如何成為人機(jī)安全的關(guān)鍵屏障
- 4 解碼特斯拉新AI芯片戰(zhàn)略 :從Dojo到AI5和AI6推理引擎
- 5 AI版“四萬(wàn)億刺激”計(jì)劃來(lái)了
- 6 2025年8月人工智能投融資觀察
- 7 8 a16z最新AI百?gòu)?qiáng)榜:硅谷頂級(jí)VC帶你讀懂全球生成式AI賽道最新趨勢(shì)
- 9 Manus跑路,大廠掉線(xiàn),只能靠DeepSeek了
- 10 地平線(xiàn)的野心:1000萬(wàn)套HSD上車(chē)