原文地址:https://blog.ixxoo.me/argparse.html
譯者:likebeta
本教程是對于Python標準庫中推薦使用的命令行解析模塊argparse的簡單介紹。
PS:還有其他兩個模塊實現這一功能,getopt(等同于C語言中的getopt())和棄用的optparse。因為argparse是基于optparse,所以用法很類似。
概念
讓我們先用ls
來展示這篇教程將要介紹的相關特性:
$ ls
cpython devguide prog.py pypy rm-unused-function.patch
$ ls pypy
ctypes_configure demo dotviewer include lib_pypy lib-python ...
$ ls -l
total 20
drwxr-xr-x 19 wena wena 4096 Feb 18 18:51 cpython
drwxr-xr-x 4 wena wena 4096 Feb 8 12:04 devguide
-rwxr-xr-x 1 wena wena 535 Feb 19 00:05 prog.py
drwxr-xr-x 14 wena wena 4096 Feb 7 00:59 pypy
-rw-r--r-- 1 wena wena 741 Feb 18 01:01 rm-unused-function.patch
$ ls --help
Usage: ls [OPTION]... [FILE]...
List information about the FILEs (the current directory by default).
Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.
...
從上面的四個命令,我們可以了解一些概念:
-
ls
命令在沒有參數的情況下也是可以使用的。默認顯示當前目錄的內容。 - 如果想讓它展示不同,需要給它更多的參數。這個例子中,我們想讓它顯示目錄
pypy
,需要指定必要的參數。因為程序需要基于這些參數確定做些什么。這個概念類似cp
, 比如最常見的cp SRC DST
。第一個參數表示你要復制什么,第二個參數表示復制到哪里去。 - 現在,我想要改變程序的行為。在示例中,我們讓它顯示更多的信息,不僅僅是文件名,這里的
-l
就是一個可選參數。 - 最后是一個幫助文檔的片段。這些幫助對于沒有使用過這個程序的人很有幫助,他們可以通過簡單的閱讀,就可以了解程序的用法。
基礎
讓我們從一個簡單的例子開始,它(幾乎)什么都不做:
import argparse
parser = argparse.ArgumentParser()
parser.parse_args()
運行:
$ python prog.py
$ python prog.py --help
usage: prog.py [-h]
optional arguments:
-h, --help show this help message and exit
$ python prog.py --verbose
usage: prog.py [-h]
prog.py: error: unrecognized arguments: --verbose
$ python prog.py foo
usage: prog.py [-h]
prog.py: error: unrecognized arguments: foo
結果分析:
- 不加任何參數運行,什么也不顯示,沒有什么用。
- 第二條展示了
argparse
模塊的好處,幾乎什么都不做,卻得到了一個很有用的幫助信息。 -
--help
參數可簡寫成-h
,是唯一預設的(不需要指定)。
定位參數
例子:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("echo")
args = parser.parse_args()
print args.echo
運行:
$ python prog.py
usage: prog.py [-h] echo
prog.py: error: the following arguments are required: echo
$ python prog.py --help
usage: prog.py [-h] echo
positional arguments:
echo
optional arguments:
-h, --help show this help message and exit
$ python prog.py foo
foo
結果分析:
- 我們用到了方法
add_argument()
,用來指定程序需要接受的命令參數,本例中的echo
。 - 現在運行程序必須指定一個參數。
- 方法
parse_args()
通過分析指定的參數返回一些數據,如本例中的echo
。 - 像魔法一樣,
argparse
自動生成這些變量,你可能已經注意到變量echo
和我們指定的參數相同。
雖然現在幫助信息已經很美觀了,但是還不夠好。例如我們知道echo
是個定位參數,但是卻不知道該參數的意思,只能通過猜或者讀源碼。下面,我們可以讓它更有幫助:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("echo", help="echo the string you use here")
args = parser.parse_args()
print args.echo
運行:
$ python prog.py -h
usage: prog.py [-h] echo
positional arguments:
echo echo the string you use here
optional arguments:
-h, --help show this help message and exit
再修改下:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", help="display a square of a given number")
args = parser.parse_args()
print args.square**2
運行如下:
$ python prog.py 4
Traceback (most recent call last):
File "prog.py", line 5, in <module>
print args.square**2
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'
運行有點問題,因為如果不指定參數類型,argparse
默認它是字符串。因此我們需要告訴argparse
該參數是整型。
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", help="display a square of a given number",
type=int)
args = parser.parse_args()
print args.square**2
運行:
$ python prog.py 4
16
$ python prog.py four
usage: prog.py [-h] square
prog.py: error: argument square: invalid int value: 'four'
可以運行了,程序能夠在執行前過濾一些錯誤的參數輸入。
可選參數
以上,展示了定位參數的用法。下面讓我們來看看如何添加可選參數:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--verbosity", help="increase output verbosity")
args = parser.parse_args()
if args.verbosity:
print "verbosity turned on"
輸出:
$ python prog.py --verbosity 1
verbosity turned on
$ python prog.py
$ python prog.py --help
usage: prog.py [-h] [--verbosity VERBOSITY]
optional arguments:
-h, --help show this help message and exit
--verbosity VERBOSITY
increase output verbosity
$ python prog.py --verbosity
usage: prog.py [-h] [--verbosity VERBOSITY]
prog.py: error: argument --verbosity: expected one argument
結果分析:
- 當指定
--verbosity
時程序就顯示一些東西,沒指定的時候就不顯示。 - 這個參數事實上是可選的,不指定它也不會出錯。如果不指定可選的參數,對應的變量就被設置為None,比如本例中的
args.verbosity
, 這就是為什么示例中的 if 沒有執行的原因。 - 幫助信息發生了點變化
- 當我們使用可選參數
--verbosity
時,也必須指定一些值。
上面的示例中可選參數--verbosity
后面接受任意的整型值,但是對于簡單的程序,實際上只需要兩種值,True
或者False
。因此可以修改上面的代碼:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--verbose", help="increase output verbosity",
action="store_true")
args = parser.parse_args()
if args.verbose:
print "verbosity turned on"
運行:
$ python prog.py --verbose
verbosity turned on
$ python prog.py --verbose 1
usage: prog.py [-h] [--verbose]
prog.py: error: unrecognized arguments: 1
$ python prog.py --help
usage: prog.py [-h] [--verbose]
optional arguments:
-h, --help show this help message and exit
--verbose increase output verbosity
結果分析:
- 現在多加一個標志來替代必須給出一些值,并修改了名稱來表達我們的意思。注意現在指定了一個新的關鍵詞
action
,并且賦值為store_ture
。如果指定了這個可選參數,args.verbose
就賦值為True
,否則就為False
。 - 多指定了值,它就會發出錯誤提示。
- 注意幫助文檔有什么不同
簡寫
如果你很熟悉命令行,你可能已經注意到我在上面已經提到了參數的簡寫,非常的簡單:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-v", "--verbose", help="increase output verbosity",
action="store_true")
args = parser.parse_args()
if args.verbose:
print "verbosity turned on"
運行如下:
$ python prog.py -v
verbosity turned on
$ python prog.py --help
usage: prog.py [-h] [-v]
optional arguments:
-h, --help show this help message and exit
-v, --verbose increase output verbosity
注意幫助信息也有相應的變化。
混合使用定位參數和可選參數
再復雜一點:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
help="display a square of a given number")
parser.add_argument("-v", "--verbose", action="store_true",
help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbose:
print "the square of {} equals {}".format(args.square, answer)
else:
print answer
運行:
$ python prog.py
usage: prog.py [-h] [-v] square
prog.py: error: the following arguments are required: square
$ python prog.py 4
16
$ python prog.py 4 --verbose
the square of 4 equals 16
$ python prog.py --verbose 4
the square of 4 equals 16
- 為了讓程序復雜點,我們重新加上了定位參數。
- 注意到參數的順序是沒有影響的。
來看看為程序加上處理重復參數的能力會怎么樣:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
help="display a square of a given number")
parser.add_argument("-v", "--verbosity", type=int,
help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbosity == 2:
print "the square of {} equals {}".format(args.square, answer)
elif args.verbosity == 1:
print "{}^2 == {}".format(args.square, answer)
else:
print answer
運行:
$ python prog.py 4
16
$ python prog.py 4 -v
usage: prog.py [-h] [-v VERBOSITY] square
prog.py: error: argument -v/--verbosity: expected one argument
$ python prog.py 4 -v 1
4^2 == 16
$ python prog.py 4 -v 2
the square of 4 equals 16
$ python prog.py 4 -v 3
16
除了最后一個暴露了一個bug,其他的看起都來運行良好。讓我們通過限制--verbosity
后面跟的值來修正:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
help="display a square of a given number")
parser.add_argument("-v", "--verbosity", type=int, choices=[0, 1, 2],
help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbosity == 2:
print "the square of {} equals {}".format(args.square, answer)
elif args.verbosity == 1:
print "{}^2 == {}".format(args.square, answer)
else:
print answer
運行:
$ python prog.py 4 -v 3
usage: prog.py [-h] [-v {0,1,2}] square
prog.py: error: argument -v/--verbosity: invalid choice: 3 (choose from 0, 1, 2)
$ python prog.py 4 -h
usage: prog.py [-h] [-v {0,1,2}] square
positional arguments:
square display a square of a given number
optional arguments:
-h, --help show this help message and exit
-v {0,1,2}, --verbosity {0,1,2}
increase output verbosity
注意幫助信息和錯誤信息都發生了變化。
現在讓我們用一種更常用的方法來處理,類似CPython
處理自己的參數(參考python --help
):
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
help="display the square of a given number")
parser.add_argument("-v", "--verbosity", action="count",
help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbosity == 2:
print "the square of {} equals {}".format(args.square, answer)
elif args.verbosity == 1:
print "{}^2 == {}".format(args.square, answer)
else:
print answer
我們引入了另一個關鍵詞count
來統計可選參數出現的次數:
$ python prog.py 4
16
$ python prog.py 4 -v
4^2 == 16
$ python prog.py 4 -vv
the square of 4 equals 16
$ python prog.py 4 --verbosity --verbosity
the square of 4 equals 16
$ python prog.py 4 -v 1
usage: prog.py [-h] [-v] square
prog.py: error: unrecognized arguments: 1
$ python prog.py 4 -h
usage: prog.py [-h] [-v] square
positional arguments:
square display a square of a given number
optional arguments:
-h, --help show this help message and exit
-v, --verbosity increase output verbosity
$ python prog.py 4 -vvv
16
- 和前面的版本相比這里多了一個關鍵詞(類似
action="store_true"
)。 - 行為上也類似
store_true
。 -
count
關鍵詞的示范,大家可能在其他地方已經看過了。 - 就像
store_ture
,如果不指定-v
,響應變量就會被設置為None
。 - 指定完整的名稱和簡寫效果是一樣的。
- 但是不爽的是,幫助信息并沒有做出有用的提示,不過可以通過修改
help
來改善這個問題。 - 最后那個輸出又暴露了程序的bug
修改一下:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
help="display a square of a given number")
parser.add_argument("-v", "--verbosity", action="count",
help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
# bugfix: replace == with >=
if args.verbosity >= 2:
print "the square of {} equals {}".format(args.square, answer)
elif args.verbosity >= 1:
print "{}^2 == {}".format(args.square, answer)
else:
print answer
運行如下:
$ python prog.py 4 -vvv
the square of 4 equals 16
$ python prog.py 4 -vvvv
the square of 4 equals 16
$ python prog.py 4
Traceback (most recent call last):
File "prog.py", line 11, in <module>
if args.verbosity >= 2:
TypeError: unorderable types: NoneType() >= int()
- 第一個輸出是正確的,修正了上個版本的問題,參數出現次數>=2時都能顯示詳細的信息。
- 第三個輸出還是有問題
再來修改下:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
help="display a square of a given number")
parser.add_argument("-v", "--verbosity", action="count", default=0,
help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbosity >= 2:
print "the square of {} equals {}".format(args.square, answer)
elif args.verbosity >= 1:
print "{}^2 == {}".format(args.square, answer)
else:
print answer
我們又加入了一個關鍵詞default
。設置它的默認值為0,這樣可以讓它兼容其他整型。注意,如果一個可選參數沒有指定,它就會被設置成None
,None
是不能和整型比較的(觸發[TypeError][5]異常
)。
運行結果:
$ python prog.py 4
16
你可以使用我們所學來做很多事情,但是這僅僅是皮毛而已。argparse
模塊非常強大,下面來看看更多的用法。
高級用法
如果我們想擴展程序的功能,而不僅僅是求平方:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("x", type=int, help="the base")
parser.add_argument("y", type=int, help="the exponent")
parser.add_argument("-v", "--verbosity", action="count", default=0)
args = parser.parse_args()
answer = args.x**args.y
if args.verbosity >= 2:
print "{} to the power {} equals {}".format(args.x, args.y, answer)
elif args.verbosity >= 1:
print "{}^{} == {}".format(args.x, args.y, answer)
else:
print answer
輸出:
$ python prog.py
usage: prog.py [-h] [-v] x y
prog.py: error: the following arguments are required: x, y
$ python prog.py -h
usage: prog.py [-h] [-v] x y
positional arguments:
x the base
y the exponent
optional arguments:
-h, --help show this help message and exit
-v, --verbosity
$ python prog.py 4 2 -v
4^2 == 16
截止到目前,我們都在利用詳細的級別來改變輸出,下面的示例演示了利用詳細的級別來顯示更多輸出:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("x", type=int, help="the base")
parser.add_argument("y", type=int, help="the exponent")
parser.add_argument("-v", "--verbosity", action="count", default=0)
args = parser.parse_args()
answer = args.x**args.y
if args.verbosity >= 2:
print "Running '{}'".format(__file__)
if args.verbosity >= 1:
print "{}^{} ==".format(args.x, args.y),
print answer
輸出:
$ python prog.py 4 2
16
$ python prog.py 4 2 -v
4^2 == 16
$ python prog.py 4 2 -vv
Running 'prog.py'
4^2 == 16
參數沖突
迄今為止,我們已經使用到了[argparse.ArgumentParser][6]
的兩個方法,來看看他的另一個方法add_mutually_exclusive_group()
。它可以讓我們指定某個參數和其他參數沖突。下面來修改下程序以對這個新方法有更多的了解:我們將加入參數--quiet
,它和參數--verbose
沖突,不能同時指定:
import argparse
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument("-v", "--verbose", action="store_true")
group.add_argument("-q", "--quiet", action="store_true")
parser.add_argument("x", type=int, help="the base")
parser.add_argument("y", type=int, help="the exponent")
args = parser.parse_args()
answer = args.x**args.y
if args.quiet:
print answer
elif args.verbose:
print "{} to the power {} equals {}".format(args.x, args.y, answer)
else:
print "{}^{} == {}".format(args.x, args.y, answer)
程序很簡單,為了演示沖突,去掉了其他功能特性展示,運行結果:
$ python prog.py 4 2
4^2 == 16
$ python prog.py 4 2 -q
16
$ python prog.py 4 2 -v
4 to the power 2 equals 16
$ python prog.py 4 2 -vq
usage: prog.py [-h] [-v | -q] x y
prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose
$ python prog.py 4 2 -v --quiet
usage: prog.py [-h] [-v | -q] x y
prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose
很好理解,我們添加最后那個輸出是為了展示靈活性,比如,指定參數時可以同時混用參數全稱和簡寫。
通過前面的學習,為了以防萬一,你可能想通過幫助信息來告訴用戶如何使用你的程序:
import argparse
parser = argparse.ArgumentParser(description="calculate X to the power of Y")
group = parser.add_mutually_exclusive_group()
group.add_argument("-v", "--verbose", action="store_true")
group.add_argument("-q", "--quiet", action="store_true")
parser.add_argument("x", type=int, help="the base")
parser.add_argument("y", type=int, help="the exponent")
args = parser.parse_args()
answer = args.x**args.y
if args.quiet:
print answer
elif args.verbose:
print "{} to the power {} equals {}".format(args.x, args.y, answer)
else:
print "{}^{} == {}".format(args.x, args.y, answer)
注意下面的幫助信息,[-v | -q]
表明了可以使用-v
或者-q
,但是不能同時使用。
$ python prog.py --help
usage: prog.py [-h] [-v | -q] x y
calculate X to the power of Y
positional arguments:
x the base
y the exponent
optional arguments:
-h, --help show this help message and exit
-v, --verbose
-q, --quiet
總結
argparse
模塊提供了比我們展示的多得多的功能。它的文檔更加詳盡和深入,并且配了大量的示例。自己去深入閱讀下,文檔很容易理解。
原文地址:Argparse Tutorial
官方文檔:argparse
另外一篇:argparse - 命令行選項與參數解析(譯)
PS:第一次翻譯文檔,感覺到英語真的太差了~~o(>_<)o ~~