Python 命令列之旅 —— 初探 argparse

HelloGitHub發表於2019-08-13

Python 命令列之旅 —— 初探 argparse

『講解開源專案系列』啟動——讓對開源專案感興趣的人不再畏懼、讓開源專案的發起者不再孤單。跟著我們的文章,你會發現程式設計的樂趣、使用和發現參與開源專案如此簡單。歡迎聯絡我們給我們投稿,讓更多人愛上開源、貢獻開源~

前言

你是否好奇過在命令列中敲入一段命令後,它是如何被解析執行的?是否考慮過由自己實現一個命令列工具,幫你執行和處理任務?是否瞭解過陪伴在你身邊的 Python 有著豐富的庫,來幫你輕鬆打造命令列工具?

彆著急,本文作為 Python 命令列之旅的第一篇將帶你逐步揭開命令列解析的面紗,介紹如何使用 Python 內建的 argparse 標準庫解析命令列,並在後續的系列文章中介紹各具特色的第三方命令列庫,講講它們的異同,進而全面地體驗這次探索的旅程。

本系列文章預設使用 Python 3 作為直譯器進行講解。
若你仍在使用 Python 2,請注意兩者之間語法和庫的使用差異哦~

介紹

argparse 作為 Python 內建的標準庫,提供了較為簡單的方式來編寫命令列介面。當你在程式中定義需要哪些引數,argparse 便會從 sys.argv 中獲取命令列輸入進行解析,對正確或非法輸入做出響應,也可以自動生成幫助資訊和使用說明。

快速開始

設定解析器

第一步要做的就是設定解析器,後續對命令列的解析就依賴於這個解析器,它能夠將命令列字串轉換為 Python 物件。
通過例項化 argparse.ArgumentParser,給定一些選填引數,我們就可以設定一個解析器:

import argparse
parser = argparse.ArgumentParser(
    description='My Cmd Line Program',
)

定義引數

通過 ArgumentParser.add_argument 方法來為解析器設定引數資訊,以告訴解析器命令列字串中的哪些內容應解析為哪些型別的 Python 物件,如:

# 新增 nums 引數,在使用資訊中顯示為 num
# 其型別為 int,且支援輸入多個,且至少需要提供一個
parser.add_argument('nums',  metavar='num', type=int, nargs='+',
                    help='a num for the accumulator')
# 新增 --sum 引數,該引數被 parser 解析後所對應的屬性名為 accumulate
# 若不提供 --sum,預設值為 max 函式,否則為 sum 函式
parser.add_argument('--sum', dest='accumulate', action='store_const',
                    const=sum, default=max,
                    help='sum the nums (default: find the max)')

解析命令列

定義好引數後,就可以使用 ArgumenteParser.parse_args 方法來解析一組命令列引數字串了。

預設情況下,引數取自 sys.argv[1:],它就是你在命令列敲入的一段命令(不含檔名)所對應的一個字串列表。
比如,若你輸入 python3 cmd.py --sum 1 2 3,那麼 sys.argsv[1:] 就是 ['--sum', '1', '2', '3']

當然,也可以通過 parse_args 入參來指定一組命令列引數字串:

args = parser.parse_args(['--sum', '-1', '0', '1'])
print(args) # 結果:Namespace(accumulate=<built-in function sum>, nums=[-1, 0, 1])

業務邏輯

解析好命令列後,我們就可以從解析結果中獲取每個引數的值,進而根據自己的業務需求做進一步的處理。
比如,對於上文中所定義的 nums 引數,我們可以通過解析後的結果中的 accumulate 方法對其進行求最大值或求和(取決於是否提供 --sum 引數)。

result = args.accumulate(args.nums)
print(result)  # 基於上文的 ['--sum', '-1', '0', '1'] 引數,accumulate 為 sum 函式,其結果為 0

程式碼梳理

通過上文的講解,完成一個命令列工具的步驟是不是挺簡單易懂呢?我們將上文的程式碼彙總下,以有一個更清晰的認識:

# cmd.py
import argparse

# 1. 設定解析器
parser = argparse.ArgumentParser(
    description='My Cmd Line Program',
)

# 2. 定義引數
parser.add_argument('nums',  metavar='num', type=int, nargs='+',
                    help='a num for the accumulator')
parser.add_argument('--sum', dest='accumulate', action='store_const',
                    const=sum, default=max,
                    help='sum the nums (default: find the max)')

# 3. 解析命令列
args = parser.parse_args()

# 4. 業務邏輯
result = args.accumulate(args.nums)
print(result)

若我們需要對一組數字求和,只需執行:

$ python3 cmd.py --sum -1 0 1
0

若我們需要對一組數字求最大值,只需執行:

$ python3 cmd.py -1 0 1
1

如果給定的引數不是數字,則會報錯提示:

$ python3 cmd.py a b c
usage: cmd.py [-h] [--sum] num [num ...]
cmd.py: error: argument num: invalid int value: 'a'

我們還可以通過 -h--help 引數檢視其自動生成的使用說明和幫助:

usage: cmd.py [-h] [--sum] num [num ...]

My Cmd Line Program

positional arguments:
  num         a num for the accumulator

optional arguments:
  -h, --help  show this help message and exit
  --sum       sum the nums (default: find the max)

小結

怎麼樣?揭開命令列工具的神祕面紗後,是不是發現它並沒有想象中的困難?反倒是感受到一種簡單而又強大的優雅呢?

不過這還遠遠不是 argparse 的全部面貌。對於一些複雜的情況,比如各種型別引數、引數字首、引數組、互斥選項、巢狀解析、自定義幫助等等,我們都還沒涉及探討。

在下一篇文章中,讓我們來一起深入瞭解 argparse,感受它的魅力吧!

Python 命令列之旅 —— 初探 argparse

關注公眾號加入交流群,一起討論有趣的技術話題

相關文章