[雪峰磁針石部落格]python庫介紹-argparse:命令列選項及引數解析

書籍尋找發表於2018-08-21

快速入門

argparse是一個完整的引數處理庫。引數可以根據add_argument()的action選項觸發不同action。支援的action有儲存引數(單個,或作為列表的一部分);儲存常量的值(對布林開關true/false有特殊處理)。預設動作是儲存引數值。支援type(指定儲存型別)和dest(指定儲存變數)等引數。

然後使用函式parse_args()進行引數解析,這個函式的輸入預設是sys.argv[1:],也可以使用其他字串列表。選項使用GNU/POSIX語法處理,可以混合選項和引數值。parse_args的返回值是一個包含命令引數的Namespace。所有引數以屬性的形式存在,比如args.myoption。

下面是一個簡單的示例:argparse_short.py


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`]))

執行結果:


$ python3 argparse_short.py
Namespace(a=True, b=`val`, c=3)

長引數argparse_long.py


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`, `--witharg2=3`]
    )
)

執行結果


$ python3 argparse_long.py

Namespace(noarg=True, witharg=`val`, witharg2=3)

混合可選和必選引數:argparse_arguments.py


import argparse

parser = argparse.ArgumentParser(
    description=`Example with nonoptional arguments`,
)

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

print(parser.parse_args())

執行結果


$ python3 argparse_arguments.py 3 inches

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

$ python3 argparse_arguments.py some inches

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

$ python3 argparse_arguments.py

usage: argparse_arguments.py [-h] count units
argparse_arguments.py: error: the following arguments are
required: count, units

引數action有:

store:預設action模式,儲存值到指定變數。
store_const:儲存值在引數的const部分指定,多用於實現非布林的命令列flag。
store_true / store_false:布林開關。可以2個引數對應一個變數。
append:儲存值到列表,該引數可以重複使用。
append_const:儲存值到列表,儲存值在引數的const部分指定。
version 輸出版本資訊然後退出。

下面是各種action的示例:argparse_action.py


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_t`,
                    help=`Set a switch to true`)
parser.add_argument(`-f`, action=`store_false`,
                    default=True,
                    dest=`boolean_f`,
                    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     = {!r}`.format(results.simple_value))
print(`constant_value   = {!r}`.format(results.constant_value))
print(`boolean_t        = {!r}`.format(results.boolean_t))
print(`boolean_f        = {!r}`.format(results.boolean_f))
print(`collection       = {!r}`.format(results.collection))
print(`const_collection = {!r}`.format(results.const_collection))

執行結果如下,注意`simple_value`等被自動化轉化為大寫


$ python3 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

$ python3 argparse_action.py -s value

simple_value     = `value`
constant_value   = None
boolean_t        = False
boolean_f        = True
collection       = []
const_collection = []

$ python3 argparse_action.py -c

simple_value     = None
constant_value   = `value-to-store`
boolean_t        = False
boolean_f        = True
collection       = []
const_collection = []

$ python3 argparse_action.py -t

simple_value     = None
constant_value   = None
boolean_t        = True
boolean_f        = True
collection       = []
const_collection = []

$ python3 argparse_action.py -f

simple_value     = None
constant_value   = None
boolean_t        = False
boolean_f        = False
collection       = []
const_collection = []

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

simple_value     = None
constant_value   = None
boolean_t        = False
boolean_f        = True
collection       = [`one`, `two`, `three`]
const_collection = []

$ python3 argparse_action.py -B -A

simple_value     = None
constant_value   = None
boolean_t        = False
boolean_f        = True
collection       = []
const_collection = [`value-2-to-append`, `value-1-to-append`]

$ python3 argparse_action.py --version

argparse_action.py 1.0

可選字首

ArgumentParser函式中的選項prefix_chars可以指定字首。預設使用UNIX風格,命令列使用‘-’作為字首。可以使用windows的’/’或者其他符號。

argparse_prefix_chars.py


import argparse

parser = argparse.ArgumentParser(
    description=`Change the option prefix characters`,
    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())

執行結果


$ python3 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

$ python3 argparse_prefix_chars.py +a

Namespace(a=True, noarg=False)

$ python3 argparse_prefix_chars.py -a

Namespace(a=False, noarg=False)

$ python3 argparse_prefix_chars.py //noarg

Namespace(a=None, noarg=True)

$ python3 argparse_prefix_chars.py ++noarg

Namespace(a=None, noarg=True)

$ python3 argparse_prefix_chars.py --noarg

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

處理配置檔案中的引數

argparse_with_shlex.py


import argparse
from configparser import ConfigParser
import shlex

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)

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))

其中argparse_with_shlex.ini檔案的內容如下:


[cli]
options = -a -b 2

執行結果


$ python3 argparse_with_shlex.py

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

上面例子使用了ConfigParser來讀取配置,再用shlex來切割引數。也可以通過fromfile_prefix_chars 告知argparse輸入引數為檔案。

argparse_fromfile_prefix_chars.py


import argparse
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

執行結果


$ python3 argparse_fromfile_prefix_chars.py

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

幫助

  • 自動生成

Argparse會自動生成的幫助和版本資訊。ArgumentParser的add_help引數控制幫助的生成,預設是開啟。

argparse_with_help.py


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())

下例就關閉幫助:

argparse_without_help.py


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())

執行結果


$ 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
  • 自定義幫助

argparse_custom_help.py


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(`print_usage output:`)
parser.print_usage()
print()

print(`print_help output:`)
parser.print_help()

執行結果


$ python3 argparse_custom_help.py

print_usage output:
usage: argparse_custom_help.py [-h] [-a] [-b B] [-c C]

print_help output:
usage: argparse_custom_help.py [-h] [-a] [-b B] [-c C]

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

argparse_raw_description_help_formatter.py


import argparse

parser = argparse.ArgumentParser(
    add_help=True,
    formatter_class=argparse.RawDescriptionHelpFormatter,
    description="""
    description
        not
           wrapped""",
    epilog="""
    epilog
      not
         wrapped""",
)

parser.add_argument(
    `-a`, action="store_true",
    help="""argument
    help is
    wrapped
    """,
)

parser.print_help()

執行結果


$ python3 argparse_raw_description_help_formatter.py

usage: argparse_raw_description_help_formatter.py [-h] [-a]

    description
        not
           wrapped

optional arguments:
  -h, --help  show this help message and exit
  -a          argument help is wrapped

    epilog
      not
         wrapped

argparse_raw_text_help_formatter.py


import argparse

parser = argparse.ArgumentParser(
    add_help=True,
    formatter_class=argparse.RawTextHelpFormatter,
    description="""
    description
        not
           wrapped""",
    epilog="""
    epilog
      not
         wrapped""",
)

parser.add_argument(
    `-a`, action="store_true",
    help="""argument
    help is not
    wrapped
    """,
)

parser.print_help()

執行結果


$ python3 argparse_raw_text_help_formatter.py

usage: argparse_raw_text_help_formatter.py [-h] [-a]

    description
        not
           wrapped

optional arguments:
  -h, --help  show this help message and exit
  -a          argument
                  help is not
                  wrapped


    epilog
      not
         wrapped

argparse_metavar_type_help_formatter.py


import argparse

parser = argparse.ArgumentParser(
    add_help=True,
    formatter_class=argparse.MetavarTypeHelpFormatter,
)

parser.add_argument(`-i`, type=int, dest=`notshown1`)
parser.add_argument(`-f`, type=float, dest=`notshown2`)

parser.print_help()

執行結果


$ python3 argparse_metavar_type_help_formatter.py

usage: argparse_metavar_type_help_formatter.py [-h] [-i int] [-f
 float]

optional arguments:
  -h, --help  show this help message and exit
  -i int
  -f float

組織解析器

公共解析器:通過父子類來實現。

見argparse_parent_base.py:


import argparse

parser = argparse.ArgumentParser(add_help=False)

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

argparse_uses_parent.py


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())

注意:父類關閉了help。子類卻預設開啟了help。執行結果:


$ python3 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

引數衝突

argparse_conflict_handler_resolve.py


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`]))

執行結果


$ python3 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

argparse_conflict_handler_resolve2.py、


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`]))

執行結果


$ python3 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_default_grouping.py


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())

執行結果


$ python3 argparse_default_grouping.py -h

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

前面的使用者名稱和密碼就可以分組:

argparse_parent_with_group.py


import argparse

parser = argparse.ArgumentParser(add_help=False)

group = parser.add_argument_group(`authentication`)

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

argparse_uses_parent_with_group.py


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())

執行結果


$ python3 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 help message and exit
  --local-arg

authentication:
  --user USER
  --password PASSWORD

互斥選項

使用add_mutually_exclusive_group()可以新增互斥選項:

argparse_mutually_exclusive.py


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())

執行結果


$ python3 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

$ python3 argparse_mutually_exclusive.py -a

Namespace(a=True, b=False)

$ python3 argparse_mutually_exclusive.py -b

Namespace(a=False, b=True)

$ python3 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

巢狀解析

argparse_subparsers.py


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())

執行結果


$ python3 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

$ python3 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 directo
ry

$ python3 argparse_subparsers.py delete -r foo

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

高階引數處理

可變引數:數字N代表N的引數,?0或者1個引數。*0或者多個引數。+1或者多個引數。

argparse_nargs.py


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())

執行結果


$ python3 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 ...]

$ python3 argparse_nargs.py

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

$ python3 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)

$ python3 argparse_nargs.py --three a b c

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

$ python3 argparse_nargs.py --optional

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

$ python3 argparse_nargs.py --optional with_value

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

$ python3 argparse_nargs.py --all with multiple values

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

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

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

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

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

$ python3 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_type.py


import argparse

parser = argparse.ArgumentParser()

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

try:
    print(parser.parse_args())

except IOError as msg:
    parser.error(str(msg))

執行結果


$ python3 argparse_type.py -i 1

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

$ python3 argparse_type.py -f 3.14

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

$ python3 argparse_type.py --file argparse_type.py

Namespace(f=None, file=<_io.TextIOWrapper
name=`argparse_type.py` mode=`r` encoding=`UTF-8`>, i=None)

$ python3 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`

$ python3 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`

$ python3 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可以指定引數的選項:

argparse_choices.py


import argparse

parser = argparse.ArgumentParser()

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

print(parser.parse_args())

執行結果


$ python3 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}

$ python3 argparse_choices.py --mode read-only

Namespace(mode=`read-only`)

$ python3 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`)

檔案引數

argparse_FileType.py


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 as msg:
    parser.error(str(msg))

執行結果


$ python3 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

$ python3 argparse_FileType.py -i argparse_FileType.py -o tmp_
file.txt

Input file: <_io.TextIOWrapper name=`argparse_FileType.py`
mode=`rt` encoding=`UTF-8`>
Output file: <_io.TextIOWrapper name=`tmp_file.txt` mode=`wt`
encoding=`UTF-8`>

$ python3 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

自定義action是argparse.Action的子類可以處理add_argument中的引數定義相關的引數,並返回一個可呼叫物件。建構函式會處理引數定義,僅僅需要處理__call__函式。__call__函式中parser代表直譯器,namespace用於返回解釋結果,value為要處理的引數,option_string用於觸發action(對可選引數,永遠是None。

argparse_custom_action.py


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(`Initializing CustomAction`)
        for name, value in sorted(locals().items()):
            if name == `self` or value is None:
                continue
            print(`  {} = {!r}`.format(name, value))
        print()
        return

    def __call__(self, parser, namespace, values,
                 option_string=None):
        print(`Processing CustomAction for {}`.format(self.dest))
        print(`  parser = {}`.format(id(parser)))
        print(`  values = {!r}`.format(values))
        print(`  option_string = {!r}`.format(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)
        print()


parser = argparse.ArgumentParser()

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

results = parser.parse_args([`-a`, `value`,
                             `-m`, `multivalue`,
                             `second`])
print(results)

執行結果


$ python3 argparse_custom_action.py

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

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

Processing CustomAction for a
  parser = 4315836992
  values = `value`
  option_string = `-a`

Processing CustomAction for m
  parser = 4315836992
  values = [`multivalue`, `second`]
  option_string = `-m`

Namespace(a=`VALUE`, m=[`MULTIVALUE`, `SECOND`])

參考資料


相關文章