【轉載】Argparse簡易教程

原文地址:https://blog.ixxoo.me/argparse.html


原文:Argparse Tutorial

譯者: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,這樣可以讓它兼容其他整型。注意,如果一個可選參數沒有指定,它就會被設置成NoneNone是不能和整型比較的(觸發[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 ~~


原文地址:https://blog.ixxoo.me/argparse.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,881評論 18 139
  • linux資料總章2.1 1.0寫的不好抱歉 但是2.0已經改了很多 但是錯誤還是無法避免 以后資料會慢慢更新 大...
    數據革命閱讀 12,218評論 2 33
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,759評論 18 399
  • //Clojure入門教程: Clojure – Functional Programming for the J...
    葡萄喃喃囈語閱讀 3,749評論 0 7
  • 拖延的習慣對你的生活有影響嗎?你是如何意識到正在拖延并采取措施的?你有哪些戰勝拖延的經驗? ——第二本書《學習之道...
    Leice閱讀 276評論 0 3