日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
用什么庫(kù)寫(xiě)Python命令行程序?看這一篇就夠了

 一、前言

在近半年的 Python 命令行旅程中,我們依次學(xué)習(xí)了 argparse、docopt、click 和 fire 庫(kù)的特點(diǎn)和用法,逐步了解到 Python 命令行庫(kù)的設(shè)計(jì)哲學(xué)與演變。本文作為本次旅程的終點(diǎn),希望從一個(gè)更高的視角對(duì)這些庫(kù)進(jìn)行橫向?qū)Ρ龋偨Y(jié)它們的異同點(diǎn)和使用場(chǎng)景,以期在應(yīng)對(duì)不同場(chǎng)景時(shí)能夠分析利弊,選擇合適的庫(kù)為己所用。

創(chuàng)新互聯(lián)建站主要從事成都網(wǎng)站制作、成都做網(wǎng)站、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)大祥,十年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專(zhuān)業(yè),歡迎來(lái)電咨詢建站服務(wù):18980820575

本系列文章默認(rèn)使用 Python 3 作為解釋器進(jìn)行講解。若你仍在使用 Python 2,請(qǐng)注意兩者之間語(yǔ)法和庫(kù)的使用差異哦~

二、設(shè)計(jì)理念

在討論各個(gè)庫(kù)的設(shè)計(jì)理念之前,我們先設(shè)計(jì)一個(gè)計(jì)算器程序,其實(shí)這個(gè)例子在 argparse 庫(kù)的第一篇講解中出現(xiàn)過(guò),也就是:

  • 命令行程序接受一個(gè)位置參數(shù),它能出現(xiàn)多次,且是數(shù)字
  • 默認(rèn)情況下,命令行程序會(huì)求出給定的一串?dāng)?shù)字的最大值
  • 如果指定了選項(xiàng)參數(shù) --sum,那么就會(huì)將求出給定的一串?dāng)?shù)字的和

希望從各個(gè)庫(kù)實(shí)現(xiàn)該例子的代碼中能進(jìn)一步體會(huì)它們的設(shè)計(jì)理念。

2.1、argparse

argparse 的設(shè)計(jì)理念就是提供給你最細(xì)粒度的控制,你需要詳細(xì)地告訴它參數(shù)是選項(xiàng)參數(shù)還是位置參數(shù)、參數(shù)值的類(lèi)型是什么、該參數(shù)的處理動(dòng)作是怎樣的??傊拖袷且粋€(gè)沒(méi)有智能分析能力的初代機(jī)器人,你需要告訴它明確的信息,它才會(huì)根據(jù)給定的信息去幫助你做事情。

以下示例為 argparse 實(shí)現(xiàn)的 計(jì)算器程序:

 
 
 
 
  1. import argparse
  2. # 1. 設(shè)置解析器
  3. parser = argparse.ArgumentParser(description='Calculator Program.')
  4. # 2. 定義參數(shù)
  5. # 添加位置參數(shù) nums,在幫助信息中顯示為 num
  6. # 其類(lèi)型為 int,且支持輸入多個(gè),且至少需要提供一個(gè)
  7. parser.add_argument('nums',  metavar='num', type=int, nargs='+',
  8.                     help='a num for the accumulator')
  9. # 添加選項(xiàng)參數(shù) --sum,該參數(shù)被 parser 解析后所對(duì)應(yīng)的屬性名為 accumulate
  10. # 若不提供 --sum,默認(rèn)值為 max 函數(shù),否則為 sum 函數(shù)
  11. parser.add_argument('--sum', dest='accumulate', action='store_const',
  12.                     const=sum, default=max,
  13.                     help='sum the nums (default: find the max)')
  14. # 3. 解析參數(shù)
  15. args = parser.parse_args(['--sum', '1', '2', '3'])
  16. print(args) # 結(jié)果:Namespace(accumulate=, nums=[1, 2, 3])
  17. # 4. 業(yè)務(wù)邏輯
  18. result = args.accumulate(args.nums)
  19. print(result)  # 基于上文的 ['--sum', '1', '2', '3'] 參數(shù),accumulate 為 sum 函數(shù),其結(jié)果為 6

從上述示例可以看到,我們需要通過(guò) add_argument 很明確地告訴 argparse 參數(shù)長(zhǎng)什么樣:

  • 它是位置參數(shù) nums,還是選項(xiàng)參數(shù) --sum
  • 它的類(lèi)型是什么,比如 type=int 表示類(lèi)型是 int
  • 這個(gè)參數(shù)能重復(fù)出現(xiàn)幾次,比如 nargs='+' 表示至少提供 1 個(gè)
  • 參數(shù)的是存什么的,比如 action='store_const' 表示存常量

然后它才根據(jù)給定的這些元信息來(lái)解析命令行參數(shù)(也就是示例中的 ['--sum', '1', '2', '3'])。

這是很計(jì)算機(jī)的思維,雖然冗長(zhǎng),但也帶來(lái)了靈活性。

2.2、docopt

從 argparse 的理念可以看出,它是命令式的。這時(shí)候 docopt 另辟蹊徑,聲明式是不是也可以?一個(gè)命令行程序的幫助信息其實(shí)已然包含了這個(gè)命令行的完整元信息,那不就可以通過(guò)定義幫助信息來(lái)定義命令行?docopt 就是基于這樣的想法去設(shè)計(jì)的。

聲明式的好處在于只要你掌握了聲明式的語(yǔ)法,那么定義命令行的元信息就會(huì)很簡(jiǎn)單。

以下示例為 docopt 實(shí)現(xiàn)的 計(jì)算器程序:

 
 
 
 
  1. # 1. 定義接口描述/幫助信息
  2. """Calculator Program.
  3. Usage:
  4.   calculator.py [--sum] ...
  5.   calculator.py (-h | --help)
  6. Options:
  7.   -h --help     Show help.
  8.   --sum         Sum the nums (default: find the max).
  9. """
  10. from docopt import docopt
  11. # 2. 解析命令行
  12. arguments = docopt(__doc__, options_first=True, argv=['--sum', '1', '2', '3'])
  13. print(arguments) # 結(jié)果:{'--help': False, '--sum': True, '': ['1', '2', '3']}
  14. # 3. 業(yè)務(wù)邏輯
  15. nums = (int(num) for num in arguments[''])
  16. if arguments['--sum']:
  17.     result = sum(nums)
  18. else:
  19.     result = max(nums)
  20. print(result) # 基于上文的 ['--sum', '1', '2', '3'] 參數(shù),處理函數(shù)為 sum 函數(shù),其結(jié)果為 6

從上述示例可以看到,我們通過(guò) __doc__ 定義了接口描述,這和 argparse 中 add_argument是等價(jià)的,然后 docopt 便會(huì)根據(jù)這個(gè)元信息把命令行參數(shù)轉(zhuǎn)換為一個(gè)字典。業(yè)務(wù)邏輯中就需要對(duì)這個(gè)字典進(jìn)行處理。

對(duì)比與 argparse:

  • 對(duì)于更為復(fù)雜的命令程序,元信息的定義上 docopt 會(huì)更加簡(jiǎn)單
  • 然而在業(yè)務(wù)邏輯的處理上,由于 argparse 在一些簡(jiǎn)單參數(shù)的處理上會(huì)更加便捷(比如示例中的情形),相對(duì)來(lái)說(shuō) docopt 轉(zhuǎn)換為字典后就把所有處理交給業(yè)務(wù)邏輯的方式會(huì)更加復(fù)雜

2.3、click

命令行程序本質(zhì)上是定義參數(shù)和處理參數(shù),而處理參數(shù)的邏輯一定是與所定義的參數(shù)有關(guān)聯(lián)的。那可不可以用函數(shù)和裝飾器來(lái)實(shí)現(xiàn)處理參數(shù)邏輯與定義參數(shù)的關(guān)聯(lián)呢?而 click 正好就是以這種使用方式來(lái)設(shè)計(jì)的。

click 使用裝飾器的好處就在于用裝飾器優(yōu)雅的語(yǔ)法將參數(shù)定義和處理邏輯整合在一起,從而暗示了路由關(guān)系。相比于 argparse 和 docopt 需要自行對(duì)解析后的參數(shù)來(lái)做路由關(guān)系,簡(jiǎn)單了不少。

以下示例為 click 實(shí)現(xiàn)的 計(jì)算器程序:

 
 
 
 
  1. import sys
  2. import click
  3. sys.argv = ['calculator.py', '--sum', '1', '2', '3']
  4. # 2. 定義參數(shù)
  5. @click.command()
  6. @click.argument('nums', nargs=-1, type=int)
  7. @click.option('--sum', 'use_sum', is_flag=True, help='sum the nums (default: find the max)')
  8. # 1. 業(yè)務(wù)邏輯
  9. def calculator(nums, use_sum):
  10.     """Calculator Program."""
  11.     print(nums, use_sum) # 輸出:(1, 2, 3) True
  12.     if use_sum:
  13.         result = sum(nums)
  14.     else:
  15.         result = max(nums)
  16.     print(result) # 基于上文的 ['--sum', '1', '2', '3'] 參數(shù),處理函數(shù)為 sum 函數(shù),其結(jié)果為 6
  17. calculator()

從上述示例可以看出,參數(shù)和對(duì)應(yīng)的處理邏輯非常好地綁定在了一起,看上去就很直觀,使得我們可以明確了解參數(shù)會(huì)怎么處理,這在有大量參數(shù)時(shí)顯得尤為重要,這邊是 click 相比于 argparse 和 docopt 最明顯的優(yōu)勢(shì)。

此外,click 還內(nèi)置了很多實(shí)用工具和額外能力,比如說(shuō) Bash 補(bǔ)全、顏色、分頁(yè)支持、進(jìn)度條等諸多實(shí)用功能,可謂是如虎添翼。

2.4、firefire

則是用一種面向廣義對(duì)象的方式來(lái)玩轉(zhuǎn)命令行,這種對(duì)象可以是類(lèi)、函數(shù)、字典、列表等,它更加靈活,也更加簡(jiǎn)單。你都不需要定義參數(shù)類(lèi)型,fire 會(huì)根據(jù)輸入和參數(shù)默認(rèn)值來(lái)自動(dòng)判斷,這無(wú)疑進(jìn)一步簡(jiǎn)化了實(shí)現(xiàn)過(guò)程。

以下示例為 fire 實(shí)現(xiàn)的 計(jì)算器程序:

 
 
 
 
  1. import sys
  2. import fire
  3. sys.argv = ['calculator.py', '1', '2', '3', '--sum']
  4. builtin_sum = sum
  5. # 1. 業(yè)務(wù)邏輯
  6. # sum=False,暗示它是一個(gè)選項(xiàng)參數(shù) --sum,不提供的時(shí)候?yàn)?nbsp;False
  7. # *nums 暗示它是一個(gè)能提供任意數(shù)量的位置參數(shù)
  8. def calculator(sum=False, *nums):
  9.     """Calculator Program."""
  10.     print(sum, nums) # 輸出:True (1, 2, 3)
  11.     if sum:
  12.         result = builtin_sum(nums)
  13.     else:
  14.         result = max(nums)
  15.     print(result) # 基于上文的 ['1', '2', '3', '--sum'] 參數(shù),處理函數(shù)為 sum 函數(shù),其結(jié)果為 6
  16. fire.Fire(calculator)

從上述示例可以看出,fire 提供的方式無(wú)疑是最簡(jiǎn)單、并且最 Pythonic 的了。我們只需關(guān)注業(yè)務(wù)邏輯,而命令行參數(shù)的定義則和函數(shù)參數(shù)的定義融為了一體。

不過(guò),有利自然也有弊,比如 nums 并沒(méi)有說(shuō)是什么類(lèi)型,也就意味著輸入字符串'abc'也是合法的,這就意味著一個(gè)嚴(yán)格的命令行程序必須在自己的業(yè)務(wù)邏輯中來(lái)對(duì)期望的類(lèi)型進(jìn)行約束。

三、橫向?qū)Ρ?/h3>

最后,我們橫向?qū)Ρ认耡rgparse、docopt、click 和 fire 庫(kù)的各項(xiàng)功能和特點(diǎn):

Python 的命令行庫(kù)種類(lèi)繁多、各具特色。結(jié)合上面的總結(jié),可以選擇出符合使用場(chǎng)景的庫(kù),如果幾個(gè)庫(kù)都符合,那么就根據(jù)你更偏愛(ài)的風(fēng)格來(lái)選擇。這些庫(kù)都很優(yōu)秀,其背后的思想很是值得我們學(xué)習(xí)和擴(kuò)展。


新聞標(biāo)題:用什么庫(kù)寫(xiě)Python命令行程序?看這一篇就夠了
轉(zhuǎn)載來(lái)源:http://www.5511xx.com/article/coheegg.html