argparse - 命令行選項與參數解析(轉)

argparse - 命令行選項與參數解析(譯)Mar 30, 2013

原文:argparse – Command line option and argument parsingpython

譯者:youngsterxyfgit

argparse模塊做爲optparse的一個替代被添加到Python2.7。argparse的實現支持一些不易於添加到optparse以及要求向後不兼容API變化的特性,所以以一個新模塊添加到標準庫。github

與optparse相比較

argparse的API相似於optparse,甚至在不少狀況下經過更新所使用的類名和方法名,使用argparse做爲一個簡單的替代。然而,有些地方在添加新特性時不能保持直接兼容性。bash

你必須視狀況決定是否升級已有的程序。若是你已編寫了額外的代碼以彌補optparse的侷限,也許你想升級程序以減小你須要維護的代碼量。若argparse在全部部署平臺上均可用,那麼新的程序應儘量使用argparse。app

設置一個解析器

使用argparse的第一步就是建立一個解析器對象,並告訴它將會有些什麼參數。那麼當你的程序運行時,該解析器就能夠用於處理命令行參數。svn

解析器類是 ArgumentParser 。構造方法接收幾個參數來設置用於程序幫助文本的描述信息以及其餘全局的行爲或設置。函數

import argparse
parser = argparse.ArgumentParser(description='This is a PyMOTW sample program')

定義參數

argparse是一個全面的參數處理庫。參數能夠觸發不一樣的動做,動做由 add_argument() 方法的 action 參數指定。 支持的動做包括保存參數(逐個地,或者做爲列表的一部分),當解析到某參數時保存一個常量值(包括對布爾開關真/假值的特殊處理),統計某個參數出現的次數,以及調用一個回調函數。工具

默認的動做是保存參數值。在這種狀況下,若是提供一個類型,那麼在存儲以前會先把該參數值轉換成該類型。若是提供 dest 參數,參數值就保存爲命令行參數解析時返回的命名空間對象中名爲該 dest 參數值的一個屬性。ui

解析一個命令行

定義了全部參數以後,你就能夠給 parse_args() 傳遞一組參數字符串來解析命令行。默認狀況下,參數是從 sys.argv[1:] 中獲取,但你也能夠傳遞本身的參數列表。選項是使用GNU/POSIX語法來處理的,因此在序列中選項和參數值能夠混合。this

parse_args() 的返回值是一個命名空間,包含傳遞給命令的參數。該對象將參數保存其屬性,所以若是你的參數 dest"myoption",那麼你就能夠args.myoption 來訪問該值。

簡單示例

如下簡單示例帶有3個不一樣的選項:一個布爾選項(-a),一個簡單的字符串選項(-b),以及一個整數選項(-c)。

import argparse

parser = argparse.ArgumentParser(description='Short sample app')

parser.add_argument('-a', action="store_true", default=False)
parser.add_argument('-b', action="store", dest="b")
parser.add_argument('-c', action="store", dest="c", type=int)

print parser.parse_args(['-a', '-bval', '-c', '3'])

有幾種方式傳遞值給單字符選項。以上例子使用了兩種不一樣的形式,-bval-c val

$ python argparse_short.py
Namespace(a=True, b='val', c=3)

在輸出中與'c'關聯的值是一個整數,由於程序告訴ArgumentParser在保存以前先轉換該參數。

「長」選項名字,即選項的名字多於一個字符,以相同的方式進行處理。

import argparse

parser = argparse.ArgumentParser(description='Example with long option names')

parser.add_argument('--noarg', action="store_true", default=False)
parser.add_argument('--witharg', action="store", dest="witharg")
parser.add_argument('--witharg2', action="store", dest="witharg2", type=int)

print parser.parse_args(['--noarg', '--witharg', 'val', '--withargs=3'])

結果也相似:

$ python argparse_long.py
Namespace(noarg=True, witharg='val', witharg2=3)

argparse區別於optparse的一個地方是對非選項參數值的處理。optparse只進行選項解析,而argparse是一個全面的命令行參數解析工具,也處理非選項參數。

import argparse

parser = argparse.ArgumentParser(description='Example with non-optional arguments')

parser.add_argument('count', action="store", type=int)
parser.add_argument('units', action="store")

print parser.parse_args()

在這個例子中,「count」參數是一個整數,「units」參數存儲爲一個字符串。其中任意一個參數若沒有在命令行中提供,或給定的值不能被轉換爲正確的類型,就會報告一個錯誤。

$ python argparse_arguments.py 3 inches

Namespace(count=3, units='inches')

$ python argparse_arguments.py some inches

usage: argparse_arguments.py [-h] count units
argparse_arguments.py: error: argument count: invalid int value: 'some'

$ python argparse_arguments.py

usage: argparse_arguments.py [-h] count units
argparse_arguments.py: error: too few arguments

參數動做

argparse內置6種動做能夠在解析到一個參數時進行觸發:

store 保存參數值,可能會先將參數值轉換成另外一個數據類型。若沒有顯式指定動做,則默認爲該動做。

store_const 保存一個被定義爲參數規格一部分的值,而不是一個來自參數解析而來的值。這一般用於實現非布爾值的命令行標記。

store_ture/store_false 保存相應的布爾值。這兩個動做被用於實現布爾開關。

append 將值保存到一個列表中。若參數重複出現,則保存多個值。

append_const 將一個定義在參數規格中的值保存到一個列表中。

version 打印關於程序的版本信息,而後退出

import argparse

parser = argparse.ArgumentParser()

parser.add_argument('-s', action='store', dest='simple_value',
        help='Store a simple value')

parser.add_argument('-c', action='store_const', dest='constant_value',
        const='value-to-store',
        help='Store a constant value')

parser.add_argument('-t', action='store_true', default=False,
        dest='boolean_switch',
        help='Set a switch to true')
parser.add_argument('-f', action='store_false', default=False,
        dest='boolean_switch',
        help='Set a switch to false')

parser.add_argument('-a', action='append', dest='collection',
        default=[],
        help='Add repeated values to a list')

parser.add_argument('-A', action='append_const', dest='const_collection',
        const='value-1-to-append',
        default=[],
        help='Add different values to list')
parser.add_argument('-B', action='append_const', dest='const_collection',
        const='value-2-to-append',
        help='Add different values to list')

parser.add_argument('--version', action='version', version='%(prog)s 1.0')

results = parser.parse_args()
print 'simple_value =', results.simple_value
print 'constant_value =', results.constant_value
print 'boolean_switch =', results.boolean_switch
print 'collection =', results.collection
print 'const_collection =', results.const_collection
$ python argparse_action.py -h

usage: argparse_action.py [-h] [-s SIMPLE_VALUE] [-c] [-t] [-f]
                          [-a COLLECTION] [-A] [-B] [--version]

optional arguments:
  -h, --help       show this help message and exit
  -s SIMPLE_VALUE  Store a simple value
  -c               Store a constant value
  -t               Set a switch to true
  -f               Set a switch to false
  -a COLLECTION    Add repeated values to a list
  -A               Add different values to list
  -B               Add different values to list
  --version        show program's version number and exit

$ python argparse_action.py -s value

simple_value = value
constant_value = None
boolean_switch = False
collection = []
const_collection = []

$ python argparse_action.py -c

simple_value = None
constant_value = value-to-store
boolean_switch = False
collection = []
const_collection = []

$ python argparse_action.py -t

simple_value = None
constant_value = None
boolean_switch = True
collection = []
const_collection = []

$ python argparse_action.py -f

simple_value = None
constant_value = None
boolean_switch = False
collection = []
const_collection = []

$ python argparse_action.py -a one -a two -a three

simple_value = None
constant_value = None
boolean_switch = False
collection = ['one', 'two', 'three']
const_collection = []

$ python argparse_action.py -B -A

simple_value = None
constant_value = None
boolean_switch = False
collection = []
const_collection = ['value-2-to-append', 'value-1-to-append']

$ python argparse_action.py --version

argparse_action.py 1.0

選項前綴

argparse選項的默認語法是基於Unix約定的,使用一個「-」前綴來表示命令行開關。argparse支持其餘前綴,所以你可使得你的程序遵守本地平臺的默認語法(例如,在Window上使用「/」)或者遵循不一樣的約定。

import argparse

parser = argparse.ArgumentParser(description='Change the option prefix charaters', 
        prefix_chars='-+/')

parser.add_argument('-a', action="store_false", default=None,
        help='Turn A off')

parser.add_argument('+a', action="store_true", default=None,
        help='Turn A on')

parser.add_argument('//noarg', '++noarg', action="store_true", default=False)

print parser.parse_args()

ArgumentParser 方法的prefix_chars 參數設置爲一個字符串,該字符串包含全部容許用來表示選項的字符。須要理解的是雖然prefix_chars包含容許用於開關的字符,但單個參數定義只能使用一種給定的開關語法。這讓你能夠對使用不一樣前綴的選項是不是別名(好比獨立於平臺的命令行語法的狀況)或替代選擇(例如,使用「+」代表打開一個開發,「-」則爲關閉一個開關)進行顯式地控制。在上述例子中,+a-a是不一樣的參數,//noarg 也能夠 ++noarg 提供,但不是 --noarg

$ python argparse_prefix_chars.py -h

usage: argparse_prefix_chars.py [-h] [-a] [+a] [//noarg]

Change the option prefix characters

optional arguments
    -h, --help  show this help message and exit
    -a  Turn A off
    +a  Turn A on
    //noarg,++noarg

$ python argparse_prefix_chars.py +a

Namespace(a=True, noarg=False)

$ python argparse_prefix_chars.py -a

Namespace(a=False, noarg=False)

$ python argparse_prefix_chars.py //noarg

Namespace(a=None, noarg=True)

$ python argparse_prefix_chars.py ++noarg

Namespace(a=None, noarg=True)

$ python argparse_prefix_chars.py --noarg

usage: argparse_prefix_chars.py [-h] [-a] [+a] [//noarg]
argparse_prefix_chars.py: error: unrecognized arguments: --noarg

參數來源

目前爲止所見的例子中,提供給解析器的參數列表來自於顯式傳遞的一個列表,或隱式地從sys.argv獲取的。顯式傳遞列表在你使用argparse來處理類命令行但並非來自命令行(好比來自一個配置文件)的指令之時比較有用。

import argparse
from ConfigParser import ConfigParser
import shlex

parser = argparse./span>ArgumentParser(description='Short sample app') parser.add_argument('-a', action="store_true", default=False) parser.add_argument('-b', action="store", dest="b") parser.add_argument('-c', action="store", dest="c", type=int) config = ConfigParser() config.read('argparse_witH_shlex.ini') config_value = config.get('cli', 'options') print 'Config: ', config_value argument_list = shlex.split(config_value) print 'Arg List:', argument_list print 'Results:', parser.parse_args(argument_list) 

shlex使得切分存儲在配置文件中的字符串很是容易。

$ python argparse_with_shlex.py

Config: -a -b 2
Arg List: ['-a', '-b', '2']
Results: Namespace(a=True, b='2', c=None)

另外一種本身處理配置文件的方法是使用fromfile_prefix_chars指定一個包含一組要待處理參數的輸入文件來告訴argparse怎樣識別參數。

import argparse
from ConfigParser import ConfigParser
import shlex

parser = argparse.ArgumentParser(description='Short sample app',
        fromfile_prefix_chars='@'
        )

parser.add_argument('-a', action="store_true", default=False)
parser.add_argument('-b', action="store", dest="b")
parser.add_argument('-c', action="store", dest="c", type=int)

print parser.parse_args(['@argparse_fromfile_prefix_chars.txt'])

該示例代碼在找到一個以@爲前綴的參數時即中止往下讀取,而後從以該參數命名的文件中查找更多的參數。例如,輸入文件argparse_fromfile_prefix_chars.txt包含一系列參數,一行一個:

-a
-b
2

那麼處理該文件產生的輸出爲:

$ python argparse_fromfile_prefix_chars.py

Namespace(a=True, b='2', c=None)

自動生成選項

通過配置argparse會自動添加選項用來生成幫助信息以及爲你的應用程序顯示版本信息。

ArgumentParser的參數add_help 控制幫助信息相關的選項。

import argparse

parser = argparse.ArgumentParser(add_help=True)

parser.add_argument('-a', action="store_true", default=False)
parser.add_argument('-b', action="store", dest="b")
parser.add_argument('-c', action="store", dest="c", type=int)

print parser.parse_args()

幫助選項(-h和–help)默認是添加的,但能夠經過將add_help設置爲false來禁用。

import argparse

parser = argparse.ArgumentParser(add_help=False)

parser.add_argument('-a', action="store_true", default=False)
parser.add_argument('-b', action="store", dest="b")
parser.add_argument('-c', action="store", dest="c", type=int)

print parser.parse_args()

雖然-h--help是事實上的請求幫助的標準選項名稱,但一些應用或argparse的使用要麼不須要提供幫助要麼須要將這兩個選項名稱用於其餘目標。

$ python argparse_with_help.py -h

usage: argparse_with_help.py [-h] [-a] [-b B] [-c C]

optional arguments:
    -h, --help  show this help message and exit
    -a
    -b B
    -c C

$ python argparse_without_help.py -h

usage: argparse_without_help.py [-a] [-b B] [-c C]
argparse_without_help.py: error: unrecognized arguments: -h

當在ArgumentParser構造方法設置版本後,就會添加版本選項(-v--version)。

import argparse

parser = argparse.ArgumentParser(version='1.0')

parser.add_argument('-a', action="store_true", default=False)
parser.add_argument('-b', action="store", dest="b")
parser.add_argument('-c', action="store", dest="c", type=int)

print parser.parse_args()

print 'This is not printed'

兩種形式的選項愛那個都會打印程序的版本字符串,而後當即退出程序。

$ python argparse_with_version.py -h

usage: argparse_with_version.py [-h] [-v] [-a] [-b B] [-c C]

optional arguments:
    -h, --help  show this help message and exit
    -v, --version   show program's version number and exit
    -a
    -b B
    -c C

$ python argparse_with_version.py -v

1.0

解析器組

argparse包含若干特性用於組織你的參數解析器,使得實現更爲簡單,也能提升輸出幫助信息的可用性。

共享解析器規則

咱們經常須要實現一套命令行程序,這些程序都帶一組參數,只是在某些方面有特殊化。例如,若是全部程序都須要在用戶進行任何實際的操做以前對用戶進行認證,那麼它們就都須要支持--user--password選項。你能夠共享的選項來定義一個「父母」解析器,而後令單個程序的解析器從該「父母」解析器繼承共享選項,這樣就沒必要顯式爲每一個ArgumentParser添加共享選項。

第一步是以共享的參數定義創建「父母」解析器。因爲「父母」解析器的後代使用者會添加相同的幫助選項,從而會引起一個異常,因此在基礎解析器中咱們關閉自動幫助選項生成。

import argparse

parser = argparse.ArgumentParser(add_help=False)

parser.add_argument('--user', action="store")
parser.add_argument('--password', action="store")

接下來,以父母解析器集建立另外一個解析器:

import argparse
import argparse_parent_base

parser = argparse.ArgumentParser(parents=[argparse_parent_base.parser])

parser.add_argument('--local-arg', action="store_true", default=False)

print parser.parse_args()

獲得的程序帶有三個選項:

$ python argparse_uses_parent.py -h

usage: argparse_uses_parent.py [-h] [--user USER] [--password PASSWORD]
                           [--local-arg]

optional arguments:
    -h, --help           show this help message and exit
    --user USER
    --password PASSWORD
    --local-arg

衝突的選項

前一個例子指出以相同的參數名字爲一個解析器添加兩個參數處理器會引起一個異常。能夠經過傳遞一個conflict_handler來改變衝突消除行爲。argparse有兩個內置的衝突處理器error(默認)和resolveresolve會基於衝突選項的添加順序來選擇一個參數處理器。

import argparse

parser = argparse.ArgumentParser(conflict_handler='resolve')

parser.add_argument('-a', action="store")
parser.add_argument('-b', action="store", help="Short alone")
parser.add_argument('--long-b', '-b', action="store", help="Long and short together")

print parser.parse_args(['-h'])

因爲最後一個處理器所給定的參數名已被使用,那麼本例中獨立選項-b將被--long-b的別名所覆蓋。

$ python argparse_conflict_handler_resolve.py

usage: argparse_conflict_handler_resolve.py [-h] [-a A] [--long-b LONG_B]

optional arguments:
    -h, --help  show this help message and exit
    -a A
    --long-b LONG_B, -b LONG_B
            Long and short together

切換add_argument()的調用順序就能夠啓用獨立的選項:

import argparse

parser = argparse.ArgumentParser(conflict_handler='resolve')

parser.add_argument('-a', action="store")
parser.add_argument('--long-b', '-b', action="store", help='Long and short together')
parser.add_argument('-b', action="store", help='Short alone')

print parser.parse_args([-h])

如今兩個選項能夠一塊兒使用了。

$ python argparse_conflict_handler_resolve2.py

usage: argparse_conflict_handler_resolve2.py [-h] [-a A] [--long-b LONG_B] [-b B]

optional arguments:
    -h, --help  show this help message and exit
    -a A
    --long-b LONG_B Long and short together
    -b B    Short alone

參數羣組

argparse能將參數定義組合成「羣組」。默認狀況下是使用兩個羣組,一個是選項的羣組,另外一個是必須的與位置相關的參數羣組。

import argparse

parser = argparse.ArgumentParser(description='Short sample app')

parser.add_argument('--optional', action="store_true", default=False)
parser.add_argument('positional', action="store")

print parser.parse_args()

羣組在輸出的幫助信息中顯示爲分開的「與位置相關的參數」和「可選參數」兩個部分:

$ python argparse_default_grouping.py

usage: argparse_default_grouping.py [-h] [--optional] positional

Short sample app

positional arguments:
    positional

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

你能夠調整羣組來提升幫助信息中羣組的邏輯性,這樣相關選項或值能記錄在一塊兒。可使用自定義羣組來重寫以前的共享選項的示例,如此在幫助信息中身份認證的選項就能夠顯示在一塊兒。

在基礎解析器中使用add_argument_group()來建立一個「身份認證」羣組,而後逐個添加身份認證相關的選項到該羣組。

import argparse

parser = argparser.ArgumentParser(add_help=False)

group = parser.add_argument_group('authentication')

group.add_argument('--user', action="store")
group.add_argument('--password', action="store")

與以前同樣,程序使用基於羣組的父母解析器列表做爲parents的值。

import argparse
import argparse_parent_with_group

parser = argparse.ArgumentParser(parents=[argparse_parent_with_group.parser])

parser.add_argument('--local-arg', action="store_true", default=False)

print parser.parse_args()

如今輸出的幫助信息一塊兒顯示身份認證選項。

$ python argparse_uses_parent_with_group.py -h

usage: argparse_uses_parent_with_group.py [-h] [--user USER] [--password PASSWORD] [--local-arg]

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

authentication:
    --user USER
    --password PASSWORD

互斥選項

定義互斥的選項是選項分組特性的一個特例,使用add_mutually_exclusive_group()而不是add_argument_group()

import argparse

parser = argparse.ArgumentParser()

group = parser.add_mutually_exclusive_group()
group.add_argument('-a', action='store_true')
group.add_argument('-b', action="store_true")

print parser.parse_args()

argparse會爲你強制執行互斥性,所以一次使用僅能給出該羣組的選項中的一個。

$ python argparse_mutually_exclusive.py -h

usage: argparse_mutually_exclusive.py [-h] [-a | -b]

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

$ python argparse_mutually_exclusive.py -a

Namespace(a=True, b=False)

$ python argparse_mutually_exclusive.py -b

Namespace(a=False, b=True)

$ python argparse_mutually_exclusive.py -a -b

usage: argparse_mutually_exclusive.py [-h] [-a | -b]
argparse_mutually_exclusive.py: error: argument -b: not allowed with argument -a

嵌套解析器

上述的父母解析器方式是在相關命令之間共享選項的方式之一。另外一種方式是將多個命令組合進一個程序中,使用子解析器來處理命令行的每一個部分。就像svnhg,以及其餘帶有多個命令行行爲或子命令的程序那樣。

一個用於處理文件系統目錄的程序可能會像這樣定義命令用於建立、刪除、以及列出一個目錄的內容:

import argparse

parser = argparse.ArgumentParser()

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

# A list command
list_parser = subparsers.add_parser('list', help='List contents')
list_parser.add_argument('dirname', action='store', help='Directory to list')

# A create command
create_parser = subparsers.add_parser('create', help='Create a directory')
create_parser.add_argument('dirname', action='store', help='New directory to create')
create_parser.add_argument('--read-only', default=False, action='store_true',
        help='Set permissions to prevent writing to the directory')

# A delete command
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='Remove the contents of the directory, too')

print parser.parse_args()

輸出的幫助信息顯示做爲「命令」的命名子解析器可以在命令行中做爲位置參數進行指定。

$ python argparse_subparsers.py -h

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

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

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

每一個子解析器也有本身的幫助信息,描述那個命令的參數和選項。

$ python argparse_subparsers.py create -h

usage: argparse_subparsers.py create [-h] [--read-only] dirname

positional arguments:
    dirname New directory to create

optional arguments:
    -h, --help  show this help message and exit
    --read-only Set permissions to prevent writing to the directory

參數被解析後,parse_args()返回的Namespace對象僅包含與指定的命令相關的值。

$ python argparse_subparsers.py delete -r foo

Namespace(dirname='foo', recursive=True)

高級參數處理

至今爲止的示例展現了簡單的布爾標識、字符串或數字參數選項、以及位置參數。對於變長參數列表、枚舉類型數據、以及常量,argparse支持複雜的參數規格。

可變形參列表

你能夠配置單個參數的定義使其可以匹配所解析的命令行的多個參數。根據須要或指望的參數個數,設置nargs爲這些標識值之一:

值  含義
N   參數的絕對個數(例如:3)
?   0或1個參數
*   0或全部參數
+   全部,而且至少一個參數
import argparse

parser = argparse.ArgumentParser()

parser.add_argument('--three', nargs=3)
parser.add_argument('--optional', nargs='?')
parser.add_argument('--all', nargs='*', dest='all')
parser.add_argument('--one-or-more', nargs='+')

print parser.parse_args()

解析器強制執行參數計數指令,生成一個精確的語法圖做爲命令幫助文本的一部分。

$ python argparse_nargs.py -h

usage: argparse_nargs.py [-h] [--three THREE THREE THREE]
                     [--optional [OPTIONAL]] [--all [ALL [ALL ...]]]
                     [--one-or-more ONE_OR_MORE [ONE_OR_MORE ...]]

optional arguments:
-h, --help            show this help message and exit
--three THREE THREE THREE
--optional [OPTIONAL]
--all [ALL [ALL ...]]
--one-or-more ONE_OR_MORE [ONE_OR_MORE ...]

$ python argparse_nargs.py

Namespace(all=None, one_or_more=None, optional=None, three=None)

$ python argparse_nargs.py --three

usage: argparse_nargs.py [-h] [--three THREE THREE THREE]
                     [--optional [OPTIONAL]] [--all [ALL [ALL ...]]]
                     [--one-or-more ONE_OR_MORE [ONE_OR_MORE ...]]
argparse_nargs.py: error: argument --three: expected 3 argument(s)

$ python argparse_nargs.py --three a b c

Namespace(all=None, one_or_more=None, optional=None, three=['a', 'b', 'c'])

$ python argparse_nargs.py --optional

Namespace(all=None, one_or_more=None, optional=None, three=None)

$ python argparse_nargs.py --optional with_value

Namespace(all=None, one_or_more=None, optional='with_value', three=None)

$ python argparse_nargs.py --all with multiple values

Namespace(all=['with', 'multiple', 'values'], one_or_more=None, optional=None, three=None)

$ python argparse_nargs.py --one-or-more with_value

Namespace(all=None, one_or_more=['with_value'], optional=None, three=None)

$ python argparse_nargs.py --one-or-more with multiple values

Namespace(all=None, one_or_more=['with', 'multiple', 'values'], optional=None, three=None)

$ python argparse_nargs.py --one-or-more

usage: argparse_nargs.py [-h] [--three THREE THREE THREE]
                     [--optional [OPTIONAL]] [--all [ALL [ALL ...]]]
                     [--one-or-more ONE_OR_MORE [ONE_OR_MORE ...]]
argparse_nargs.py: error: argument --one-or-more: expected at least one argument

參數類型

argparse將全部參數值都看做是字符串,除非你告訴它將字符串轉換成另外一種數據類型。add_argument()type參數以一個轉換函數做爲值,被ArgumentParser用來將參數值從一個字符串轉換成另外一種數據類型。

import argparse

parser = argparse.ArgumentParser()

parser.add_argument('-i', type=int)
parser.add_argument('-f', type=float)
parser.add_argument('--file', type=file)

try:
    print parser.parse_args()
except IOError, msg:
    parser.error(str(msg))

任何須要單個字符串參數的可調用對象均可以傳遞給type,包含內置類型如int(), float(), 以及file()

$ python argparse_type.py -i 1

Namespace(f=None, file=None, i=1)

$ python argparse_type.py -f 3.14

Namespace(f=3.14, file=None, i=None)

$ python argparse_type.py --file argparse_type.py

Namespace(f=None, file=<open file 'argparse_type.py', mode 'r' at 0x1004de270>, i=None)

若是類型轉換失敗,argparse會引起一個異常。TypeErrorValueError會被自動捕獲,併爲用戶轉換爲一個簡單的錯誤消息。其餘異常,以下面一個例子中輸入文件不存在,則其IOError必須由調用者來處理。

$ python argparse_type.py -i a

usage: argparse_type.py [-h] [-i I] [-f F] [--file FILE]
argparse_type.py: error: argument -i: invalid int value: 'a'

$ python argparse_type.py -f 3.14.15

usage: argparse_type.py [-h] [-i I] [-f F] [--file FILE]
argparse_type.py: error: argument -f: invalid float value: '3.14.15'

$ python argparse_type.py --file does_not_exist.txt

usage: argparse_type.py [-h] [-i I] [-f F] [--file FILE]
argparse_type.py: error: [Errno 2] No such file or directory: 'does_not_exist.txt'

要想將一個輸入參數限制爲一個預約義集中的某個值,則使用choices參數。

import argparse

parser = argparse.ArgumentParser()

parser.add_argument('--mode', choices=('read-only', 'read-write'))

print parser.parse_args()

若是--mode的參數值不是所容許的值中的一個,就會產生一個錯誤並中止執行。

$ python argparse_choices.py -h

usage: argparse_choices.py [-h] [--mode {read-only,read-write}]

optional arguments:
-h, --help            show this help message and exit
--mode {read-only,read-write}

$ python argparse_choices.py --mode read-only

Namespace(mode='read-only')

$ python argparse_choices.py --mode invalid

usage: argparse_choices.py [-h] [--mode {read-only,read-write}]
argparse_choices.py: error: argument --mode: invalid choice: 'invalid'
(choose from 'read-only', 'read-write')

文件參數

雖然文件對象能夠單個字符串參數值來實例化,但並不容許你指定訪問模式。FileType讓你可以更加靈活地指定某個參數應該是個文件,包括其訪問模式和緩衝區大小。

import argparse

parser = argparse.ArgumentParser()

parser.add_argument('-i', metavar='in-file', type=argparse.FileType('rt'))
parser.add_argument('-o', metavar='out-file', type=argparse.FileType('wt'))

try:
    results = parser.parse_args()
    print 'Input file:', results.i
    print 'Output file:', results.o
except IOError, msg:
    parser.error(str(msg))

上例中與參數名關聯的值是一個打開文件句柄。在使用完該文件後應本身負責關閉該文件。

$ python argparse_FileType.py -h

usage: argparse_FileType.py [-h] [-i in-file] [-o out-file]

optional arguments:
-h, --help   show this help message and exit
-i in-file
-o out-file

$ python argparse_FileType.py -i argparse_FileType.py -o temporary_file.\
txt

Input file: <open file 'argparse_FileType.py', mode 'rt' at 0x1004de270>
Output file: <open file 'temporary_file.txt', mode 'wt' at 0x1004de300>

$ python argparse_FileType.py -i no_such_file.txt

usage: argparse_FileType.py [-h] [-i in-file] [-o out-file]
argparse_FileType.py: error: argument -i: can't open 'no_such_file.txt': [Errno 2] No such file or directory: 'no_such_file.txt'

自定義動做

除了前面描述的內置動做以外,你也能夠提供一個實現了Action API的對象來自定義動做。做爲action傳遞給add_argument()的對象應接受描述所定義形參的實參,並返回一個可調用對象,做爲parser的實參來處理形參,namespace存放解析的結果、參數值,以及觸發動做的option_string

argparse提供了一個Action類做爲要定義的新動做的基類。構造方法是處理參數定義的,因此你只要在子類中覆蓋call()

import argparse

class CustomAction(argparse.Action):
    def __init__(self,
            option_strings,
            dest,
            nargs=None,
            const=None,
            default=None,
            type=None,
            choices=None,
            required=False,
            help=None,
            metavar=None):
        argparse.Action.__init__(self,
                option_strings=option_strings,
                dest=dest,
                nargs=nargs,
                const=const,
                default=default,
                type=type,
                choices=choices,
                required=required,
                help=help,
                metavar=metavar)
        print
        print 'Initializing CustomAction'
        for name,value in sorted(locals().items()):
            if name == 'self' or value is None:
                continue
            print ' %s = %r' % (name, value)
        return

    def __call__(self, parser, namespace, values, option_string=None):
        print
        print 'Processing CustomAction for "%s"' % self.dest
        print ' parser = %s' % id(parser)
        print ' values = %r' % values
        print ' option_string = %r' % option_string
        
        # Do some arbitrary processing of the input values
        if isinstance(values, list):
            values = [ v.upper() for v in values ]
        else:
            values = values.upper()
        # Save the results in the namespace using the destination
        # variable given to our constructor.
        setattr(namespace, self.dest, values)

parser = argparse.ArgumentParser()

parser.add_argument('-a', action=CustomAction)
parser.add_argument('-m', nargs='*', action=CustomAction)
parser.add_argument('positional', action=CustomAction)

results = parser.parse_args(['-a', 'value', '-m' 'multi-value', 'positional-value'])
print
print results

values的類型取決於nargs的值。若是該參數容許多個值,則values會是一個列表,即便其僅包含一個列表項。

option_string的值也取決於原有的參數規範。對於位置相關的、必需的參數,option_string始終爲None

$ python argparse_custom_action.py

Initializing CustomAction
    dest = 'a'
    option_strings = ['-a']
    required = False

Initializing CustomAction
    dest = 'm'
    nargs = '*'
    option_strings = ['-m']
    required = False

Initializing CustomAction
    dest = 'positional'
    option_strings = []
    required = True

Processing CustomAction for "a"
    parser = 4299616464
    values = 'value'
    option_string = '-a'

Processing CustomAction for "m"
    parser = 4299616464
    values = ['multi-value']
    option_string = '-m'

Processing CustomAction for "positional"
    parser = 4299616464
    values = 'positional-value'
    option_string = None

Namespace(a='VALUE', m=['MULTI-VALUE'], positional='POSITIONAL-VALUE')
相關文章
相關標籤/搜索