日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

Python 命令行之旅:深入 argparse(二)

系統(tǒng) 1741 0

Python 命令行之旅:深入 argparse(二)_第1張圖片


作者:HelloGitHub- Prodesire

HelloGitHub 的《講解開源項(xiàng)目》系列,項(xiàng)目地址:https://github.com/HelloGitHub-Team/Article

前言

在上一篇“深入 argparse(一)”的文章中,我們深入了解了 argparse 的包括參數(shù)動(dòng)作和參數(shù)類別在內(nèi)的基本功能,具備了編寫一個(gè)簡單命令行程序的能力。本文將繼續(xù)深入了解 argparse 的進(jìn)階玩法,一窺探其全貌,助力我們擁有實(shí)現(xiàn)復(fù)雜命令行程序的能力。

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

幫助

自動(dòng)生成幫助

當(dāng)你在命令行程序中指定 -h --help 參數(shù)時(shí),都會(huì)輸出幫助信息。而 argparse 可通過指定 add_help 入?yún)? True 或不指定,以達(dá)到自動(dòng)輸出幫助信息的目的。

          
            >>> import argparse
>>> parser = argparse.ArgumentParser(add_help=True)
>>> parser.add_argument('--foo')
>>> parser.parse_args(['-h'])
usage: [-h] [--foo FOO]

optional arguments:
  -h, --help  show this help message and exit
  --foo FOO
          
        

如果 add_help=False ,那么在命令行中指定 -h 則會(huì)報(bào)錯(cuò):

          
            >>> import argparse
>>> parser = argparse.ArgumentParser(add_help=False)
>>> parser.add_argument('--foo')
>>> parser.parse_args(['-h'])
usage: [--foo FOO]
: error: unrecognized arguments: -h
          
        

自定義幫助

ArgumentParser 使用 formatter_class 入?yún)砜刂扑敵龅膸椭袷健?
比如,通過指定 formatter_class=argparse.RawTextHelpFormatter ,我們可以讓幫助內(nèi)容遵循原始格式:

          
            >>> import argparse
>>> parser = argparse.ArgumentParser(
...     add_help=True,
...     formatter_class=argparse.RawTextHelpFormatter,
...     description="""
...     description
...         raw
...            formatted"""
... )
>>> parser.add_argument(
...     '-a', action="store_true",
...     help="""argument
...         raw
...             formatted
...     """
... )
>>>
>>> parser.parse_args(['-h'])
usage: [-h] [-a]

    description
        raw
           formatted

optional arguments:
  -h, --help  show this help message and exit
  -a          argument
                      raw
                          formatted
          
        

對(duì)比下不指定 formatter_class 的幫助輸出,就可以發(fā)現(xiàn) descirption 和 -a 兩個(gè)幫助內(nèi)容上的差異:

          
            >>> import argparse
>>> parser = argparse.ArgumentParser(
...     add_help=True,
...     description="""
...     description
...         notraw
...            formatted"""
... )
>>> parser.add_argument(
...     '-a', action="store_true",
...     help="""argument
...         notraw
...             formatted
...     """
... )
>>> parser.parse_args(['-h'])
usage: [-h] [-a]

description notraw formatted

optional arguments:
  -h, --help  show this help message and exit
  -a          argument notraw formatted
          
        

參數(shù)組

有時(shí)候,我們需要給參數(shù)分組,以使得在顯示幫助信息時(shí)能夠顯示到一起。

比如某命令行支持三個(gè)參數(shù)選項(xiàng) --user --password --push ,前兩者需要放在一個(gè)名為 authentication 的分組中以表示它們是身份認(rèn)證信息。那么我們可以用 ArgumentParser.add_argument_group 來滿足:

          
            >>> import argparse
>>> parser = argparse.ArgumentParser()
>>> group = parser.add_argument_group('authentication')
>>> group.add_argument('--user', action="store")
>>> group.add_argument('--password', action="store")
>>> parser.add_argument('--push', action='store')
>>> parser.parse_args(['-h'])
usage: [-h] [--user USER] [--password PASSWORD] [--push PUSH]

optional arguments:
  -h, --help           show this help message and exit
  --push PUSH

authentication:
  --user USER
  --password PASSWORD
          
        

可以看到,當(dāng)我們輸出幫助信息時(shí), --user --password 選項(xiàng)都出現(xiàn)在 authentication 分組中。

選項(xiàng)參數(shù)前綴

不知你是否注意到,在不同平臺(tái)上命令行程序的選項(xiàng)參數(shù)前綴可能是不同的。比如在 Unix 上,其前綴是 - ;而在 Windows 上,大多數(shù)命令行程序(比如 findstr )的選項(xiàng)參數(shù)前綴是 /

argparse 中,選項(xiàng)參數(shù)前綴默認(rèn)采用 Unix 命令行約定,也就是 - 。但它也支持自定義前綴,下面是一個(gè)例子:

          
            >>> import argparse
>>> 
>>> parser = argparse.ArgumentParser(
...     description='Option prefix',
...     prefix_chars='-+/',
... )
>>> 
>>> parser.add_argument('-power', action="store_false",
...                     default=None,
...                     help='Set power off',
...                     )
>>> parser.add_argument('+power', action="store_true",
...                     default=None,
...                     help='Set power on',
...                     )
>>> parser.add_argument('/win',
...                     action="store_true",
...                     default=False)
>>> parser.parse_args(['-power'])
Namespace(power=False, win=False)
>>> parser.parse_args(['+power', '/win'])
Namespace(power=True, win=True)
          
        

在這個(gè)例子中,我們指定了三個(gè)選項(xiàng)參數(shù)前綴 - + / ,從而:

  • 通過指定選項(xiàng)參數(shù) -power ,使得 power=False
  • 通過指定選項(xiàng)參數(shù) +power ,使得 power=True
  • 通過指定選項(xiàng)參數(shù) /win ,使得 win=True

共享解析器

有些時(shí)候我們需要共享解析器,以共享里面的參數(shù)配置。比如,我們的命令行工具需要支持對(duì)阿里云和 AWS 進(jìn)行操作,兩類操作都需要指定 AccessKeyId AccessKeySecret 來表明用戶身份和權(quán)限。那么共享解析器就顯得尤為必要,這樣就可以少去重復(fù)代碼。

我們可以這樣做,在 base.py 中定義一個(gè)父解析器,存放 AccessKey 相關(guān)參數(shù)配置,作為公用的解析器。由于后續(xù)的子解析器會(huì)自動(dòng)生成幫助信息,這里的父解析器指定 add_help=False 以不自動(dòng)生成幫助信息:

          
            # bash.py
import argparse

parser = argparse.ArgumentParser(add_help=False)

parser.add_argument('--ak-id', action="store")
parser.add_argument('--ak-secret', action="store")
          
        

然后就可以分別在 ali.py aws.py 中分別定義子解析器,通過 parents 入?yún)⒅付ㄉ鲜龈附馕銎鳎瑥亩^承公共的參數(shù),并實(shí)現(xiàn)各自的參數(shù):

          
            # ali.py
import argparse
import base

parser = argparse.ArgumentParser(
    parents=[base.parser],
)

parser.add_argument('--ros',
                    action="store_true",
                    default=False,
                    help='Using ROS service to orchestrate cloud resources')

print(parser.parse_args())
          
        
          
            # aws.py
import argparse
import base

parser = argparse.ArgumentParser(
    parents=[base.parser],
)

parser.add_argument('--cloudformation',
                    action="store_true",
                    default=False,
                    help='Using CloudFormation service to orchestrate cloud resources')

print(parser.parse_args())
          
        

最終通過 -h 參數(shù)分別看 ali.py aws.py 所支持的參數(shù),其中共同參數(shù)為 --ak-id --ak-secret ,特定參數(shù)分別為 --ros --cloudformation

          
            $ python3 ali.py -h

usage: ali.py [-h] [--ak-id AK_ID] [--ak-secret AK_SECRET] [--ros]

optional arguments:
  -h, --help            show this help message and exit
  --ak-id AK_ID
  --ak-secret AK_SECRET
  --ros                 Using ROS service to orchestrate cloud resources
          
        
          
            $ python3 aws.py -h

usage: aws.py [-h] [--ak-id AK_ID] [--ak-secret AK_SECRET] [--cloudformation]

optional arguments:
  -h, --help            show this help message and exit
  --ak-id AK_ID
  --ak-secret AK_SECRET
  --cloudformation      Using CloudFormation service to orchestrate cloud
                        resources
          
        

嵌套解析器

我們之前介紹的命令行中,使用形式通常是 cli --a --b xxx 。但還有一種極為常見的命令行使用方式是 cli subcmd --a --b xxx 。比如當(dāng)我們要通過 git 推送標(biāo)簽時(shí),會(huì)用到 git push --tags

通過實(shí)現(xiàn)嵌套解析器,我們可以很容易地對(duì)這種子命令的形式進(jìn)行解析。

在嵌套解析器中,我們定義一個(gè)父解析器來作為整個(gè)命令行的入口,再分別定義N個(gè)子解析器來對(duì)應(yīng)N個(gè)子命令,由此即可實(shí)現(xiàn)整個(gè)功能。

在下面這個(gè)例子中,我們支持 create delete 兩個(gè)子命令,用來創(chuàng)建或刪除指定路徑。而 delete 命令支持 --recursive 參數(shù)來表明是否遞歸刪除指定路徑:

          
            # cli.py
import argparse

parser = argparse.ArgumentParser()

subparsers = parser.add_subparsers(help='commands')

# Create
create_parser = subparsers.add_parser(
    'create', help='Create a directory')
create_parser.add_argument(
    'dirname', action='store',
    help='New directory to create')

# Delete
delete_parser = subparsers.add_parser(
    'delete', help='Remove a directory')
delete_parser.add_argument(
    'dirname', action='store', help='The directory to remove')
delete_parser.add_argument(
    '--recursive', '-r', default=False, action='store_true',
    help='Recursively remove the directory',
)

print(parser.parse_args())
          
        

直接指定 -h 來查看所支持的子命令和參數(shù)選項(xiàng):

          
            $ python3 cli.py -h

usage: cli.py [-h] {create,delete} ...

positional arguments:
  {create,delete}  commands
    create         Create a directory
    delete         Remove a directory

optional arguments:
  -h, --help       show this help message and exit
          
        

直接指定 delete -h 來查看 delete 子命令支持的參數(shù)選項(xiàng):

          
            $ python3 cli.py delete -h

usage: cli.py delete [-h] [--recursive] dirname

positional arguments:
  dirname          The directory to remove

optional arguments:
  -h, --help       show this help message and exit
  --recursive, -r  Recursively remove the directory
          
        

自定義動(dòng)作

在上一篇“深入 argparse (一)”的文章中介紹過8種參數(shù)動(dòng)作,可以說是覆蓋了絕大部分場(chǎng)景。但是也會(huì)有一些特定需求無法被滿足,比如希望獲取到的參數(shù)值都是大寫。在這種情況下,自定義動(dòng)作就派上了用場(chǎng)。

實(shí)現(xiàn)一個(gè)自定義動(dòng)作類,需繼承自 argparse.Action ,這個(gè)自定義動(dòng)作類要傳入到 ArgumentParser.add_argument action 入?yún)ⅰ.?dāng)解析器解析參數(shù)時(shí),會(huì)調(diào)用該類的 __call__ 方法,該方法的簽名為 __call__(self, parser, namespace, values, option_string=None) ,其中:

  • parser 為解析器實(shí)例
  • namespace 存放解析結(jié)果
  • values 即命令行中傳入的參數(shù)值
  • option_string 為參數(shù)選項(xiàng)

在下面的例子中,我們通過 --words 傳入單詞,并在自定義動(dòng)作類中將其值轉(zhuǎn)換為大寫:

          
            # cli.py
import argparse

class WordsAction(argparse.Action):

    def __call__(self, parser, namespace, values,
                 option_string=None):
        print(f'parser = {parser}')
        print(f'values = {values!r}')
        print(f'option_string = {option_string!r}')

        values = [v.upper() for v in values]
        setattr(namespace, self.dest, values)


parser = argparse.ArgumentParser()
parser.add_argument('--words', nargs='*', action=WordsAction)

results = parser.parse_args()
print(results)
          
        
          
            $ python3 cli.py --words foo bar

parser = ArgumentParser(prog='cli.py', usage=None, description=None, formatter_class=
            
              , conflict_handler='error', add_help=True)
values = ['foo', 'bar']
option_string = '--words'
Namespace(words=['FOO', 'BAR'])
            
          
        

小節(jié)

通過對(duì) argparse 由淺入深的介紹,相信你已經(jīng)全面了解了 argparse 的威力,也具備了開發(fā)命令行工具的能力。但“紙上得來終覺淺,絕知此事要躬行”。

在下篇文章中,將帶大家一起用 argparse 實(shí)現(xiàn)日常工作中常見的 git 命令,想想是不是有些興奮呢?


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 宁武县| 云南省| 宁阳县| 丹巴县| 高邑县| 葵青区| 大新县| 吉首市| 礼泉县| 河西区| 平远县| 荃湾区| 石泉县| 稷山县| 湖州市| 普陀区| 金乡县| 茂名市| 枝江市| 鹿邑县| 渝北区| 丘北县| 怀化市| 门源| 会昌县| 广饶县| 博野县| 咸宁市| 会泽县| 盐亭县| 涞水县| 昂仁县| 宜春市| 武鸣县| 石屏县| 眉山市| 株洲县| 博白县| 商丘市| 峨山| 上林县|