如果說 GUI(Graphical User Interface,圖形化使用者介面)是給人們使用的介面,那 CUI (Character User Interface,字元使用者介面)就是給機器人跑自動化程式所使用的介面(嗯 Linux 使用者表示我們也都在用 CUI),總之是指一個在終端機裡僅靠輸入文字操作的介面,讓程式藉由傳入參數來完善功能。
本文用詞說明
因為命令列的參數選項跟 Python 方法(Method)的選項參數中文命名很混淆視聽(其實英文也都叫做 Argument),所以本文後面將統一用詞以區分彼此的不同,針對以下這一行命令列:
$ python sample.py --foo FOO
--foo
為「參數」,FOO
為「項目」,而 Python 中的參數語法叫「命名參數」。
基本用法
剖析真實的程式來思考如何用 argparse 實現參數行為。
以 rm 為例
以下示範寫一個 rm_arg.py 實現 rm 的參數行為:
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument("files", nargs="+", metavar="FILE")
parser.add_argument("-f", "--force", action="store_true", help="ignore ...")
parser.add_argument("-i", action="store_true", help="prompt before ...")
parser.add_argument("-I", action="store_true", help="Prompt once ...")
parser.add_argument("--interactive", metavar="WHEN", default="never", choices=["never", "once", "always"], help="Prompt according to WHEN ...")
parser.add_argument("--one-file-system", action="store_true", help="When removing a hierarchy recursively ...")
parser.add_argument("--no-preserve-root", action="store_true", help="Do not treat ...")
parser.add_argument("--preserve-root", action="store_true", help="Do not remove ...")
parser.add_argument("-r", "-R", "--recursive", action="store_true", help="Remove directories ...")
parser.add_argument("-d", "--dir", action="store_true", help="Remove empty directories ...")
parser.add_argument("-v", "--verbose", action="store_true", help="Verbose mode ...")
parser.add_argument('--version', action='version', version='%(prog)s 1.0', help="Display version ...")
args = parser.parse_args()
最後一行一定要寫才會去解析系統參數,可以在終端機輸入 python rm_arg.py --help
以查看 Help 文字的效果。
add_argument
的命名參數説明:
default
設定參數不存在時的預設值,不寫的話其值為 None。nargs
指定此參數需要的項目個數,不寫的話為 1,常用以下方式指定:N
一個整數數字(預設行為)"?"
0個或1個"*"
0個或多個"+"
1個或多個
choices
指定可用項目,不寫表示無限制。metavar
自定 Help 文字裡此參數的項目占位符(Placeholder),不寫會用大寫的參數名稱。nargs
為N
時建議使用同長度的 Tuple,例如metavar=("x", "y", "z")
- 其他的情況指定一個喜歡的字串即可
action
指定參數存在時的特別行為,常用以下值:"store_true"
參數存在時為True
,預設值為False
"append"
表示此參數可指定複數次,以 List 型別儲存。留意:無指定default
也無設定此參數的情況下會取得None
值。
required
設定為True
表示此參數為必須。
取得參數值
使用 .
(Dot Notation) 取值,注意參數名中的 -
(Dash) 會自動轉成底線以符合 Python 的變數命名規則,若想更換屬性的命名可以使用 dest
命名參數(詳見下方的 shutdown 範例說明)。
print(args.files)
print(args.one_file_system)
也可以藉由 vars
函式來歷遍所有可用 Attribute。
for key, value in vars(args).items():
print(key, value)
進階用法
在創建 ArgumentParser 時可以藉由帶入額外命名參數來進一步客製化 argparse 行為。
加入互斥的選項
有時多個參數為互相排斥,也就是多個參數只能擇一,可以利用 add_mutually_exclusive_group
來達成:
>>> parser = ArgumentParser()
>>> group = parser.add_mutually_exclusive_group(required=True)
>>> group.add_argument("--max", action="store_true")
>>> group.add_argument("--min", action="store_true")
>>> parser.print_help()
usage: min_max.py [-h] (--max | --min)
optional arguments:
-h, --help show this help message and exit
--max
--min
add_mutually_exclusive_group
的命名參數 required
預設值為 False
,也就是要嘛不寫要嘛也只能寫一個的意思。
自定 Help 文字
帶入 prog
、usage
、description
、epilog
等命名參數來進一步客製化 Help 文字訊息。
>>> parser = ArgumentParser(
prog="PROG_NAME",
usage="%(prog)s [OPTIONS]",
description="DESCRIPTION SECTION",
epilog="EPILOG SECTION")
>>> parser.print_help()
usage: PROG_NAME [OPTIONS]
DESCRIPTION SECTION
options:
-h, --help show this help message and exit
EPILOG SECTION
為參數說明列表分群組
可以使用 add_argument_group
來在 Help 文字中分群組說明不同參數的用途,對參數的功能沒有實質上的影響,只是排版好看。使用方法很簡單,就是在原有的 parser 呼叫 add_argument_group
方法創建群組後把參數加在群組裡即可,可以參見下方的 shutdown 範例。
改變參數的前綴字符
若想使用 -
(dash) 以外的字符來標記為參數,可以使用 prefix_chars
命名參數,例如 Windows 平台很喜歡用 /
(slash):
>>> parser = ArgumentParser(prefix_chars='/')
>>> parser.print_help()
usage: sample.py [/h]
optional arguments:
/h, //help show this help message and exit
其他用法
留意本段落的範例寫法:
>>> parser.parse_args(['-i', '-foo', 'BOO'])
等同於去解析終端機中的以下輸入:
$ python sample.py -i -foo BOO
強制完整參數名稱
argparse 的預設行為允許使用任意長度的參數名稱縮寫(若不與其他參數名稱衝突)。
>>> parser = ArgumentParser()
>>> parser.add_argument("--context")
>>>
>>> parser.parse_args(["--c", "123"])
Namespace(context="123")
>>> parser.parse_args(["--con", "123"])
Namespace(context="123")
命名參數中帶入 allow_abbrev=False
可以禁止自動辨識縮寫:
>>> parser = ArgumentParser(allow_abbrev=False)
>>> parser.add_argument("--context")
>>>
>>> parser.parse_args(["--c", "123"])
error: unrecognized arguments: --c 123
An exception has occurred, use %tb to see the full traceback.
以 shutdown 為例
最後示範寫一個 shutdown_arg.py
實現 Windows 平台 shutdown 的參數行為:
from argparse import ArgumentParser
p = ArgumentParser(
add_help=False,
allow_abbrev=False,
prefix_chars='/',
description="可讓您一次關閉或重新開機本機或遠端電腦。",
usage="%(prog)s [/i | /l | /s | /sg | /r | /g | /a | /p | /h | /e | /o] [/hybrid] [/fw] [/f] [/m \\computer][/t xxx][/d [p|u:]xx:yy [/c 'comment']]",
epilog="備註:使用者必須獲指派關閉系統使用者權限...",
)
action_group = p.add_mutually_exclusive_group(required=False)
action_group.add_argument("/i", action="store_const", const="i", dest="action", help="顯示 [遠端關機 ] 方塊 ...")
action_group.add_argument("/l", action="store_const", const="l", dest="action", help="立即登出目前的使用者 ...")
# ...
action_group.add_argument("/h", action="store_const", const="h", dest="action", help="如果已啟用休眠,請將本機電腦放入休眠狀態 ...")
# ...
action_group.add_argument("/o", action="store_const", const="o", dest="action", help="移至 [ 進階開機選項] 功能表並重新啟動裝置 ...")
option_group = p.add_argument_group(title="other options")
option_group.add_argument("/hybrid", action="store_true", help="關閉裝置並準備快速啟動 ...")
option_group.add_argument("/f", action="store_true", help="強制執行應用程式關閉而不警告使用者。")
option_group.add_argument("/m", metavar="\\\\", help="指定目的電腦。 無法搭配 /l 選項使用。")
option_group.add_argument("/t", default=30, type=int, metavar="", help="將關機之前的逾時期間設定為 xxx 秒 ...")
comment_group = p.add_argument_group(title="add comment")
comment_group.add_argument("/d", metavar="[p | u:]:", action="append", dest="comment", help="列出系統重新開機或關機的原因 ...")
comment_group.add_argument("/c", metavar="", action="append", dest="comment", help="可以讓您詳細註解關機的原因 ...")
p.add_argument("/help", action="help", help="在命令提示字元中顯示說明 ...")
args = p.parse_args()
if args.comment:
comment_parser = ArgumentParser(prefix_chars='/')
comment_parser .add_argument("reason_code")
comment_parser .add_argument("detail", nargs="?", default="")
comment_args = comment_parser .parse_args(args.comment)
眼尖的同學們會發現此例子中有使用到 -h
參數,也就是預設顯示 Help 的參數,可以在創建 ArgumentParser 時帶入 add_help=False
以取消預設的 /h
、//help
參數,然後再自己加入一個指定 action="help"
的參數來保留 Help 功能。
add_argument
的命名參數説明:
type
可以將參數項目轉為指定型別,預設為str
action
指定參數存在時的特別行為:"store_const"
參數存在時為使用const
命名參數指定的值,否則使用default
"append"
表示此參數的項目值將會 Append 至 List 列表- 若存在
dest
命名參數,存至其指定的命名屬性,預設存至以參數命名的屬性
- 若存在
將參數的項目設值寫入此 Attribute 名稱中dest - 以
/d
為例,參數選項/d 111
將以args.comment = ["111"]
方式存取
- 以
另外還新增了另一個
專門負責解析 Comment 字串,可以藉由以下程式碼查看屬性值。
if args.comment:
#...
print(comment_args .reason_code)
print(comment_args .detail)
References
- Argparse Tutorial – Python Documentation
- argparse – Python Documentation
(網頁的 Top Bar 左邊可以切換顯示語言與 Python 版本)