1. Install

About 6 min

1. Install

内置于python,不需要安装

https://docs.python.org/3/library/argparse.htmlopen in new window

2. Base

2.1. hello example

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--integer', type=int)
args = parser.parse_args()
# 自带的函数,来打印 help信息
parser.print_help()

print(args)
# . 来引用
print(args.integer)
'''
# python t.py --integer=1
$ python t.py --integer 1
usage: t.py [-h] [--integer INTEGER]

optional arguments:
  -h, --help         show this help message and exit
  --integer INTEGER
Namespace(integer=1)
1
'''
>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--integer', type=int)
_StoreAction(option_strings=['--integer'], dest='integer', nargs=None, const=None, default=None, type=<class 'int'>, choices=None, required=False, help=None, metavar=None)
>>> parser.parse_args('--integer=1'.split())
Namespace(integer=1)

2.2. 帮助提示

两处帮助提示。

import argparse

# description是此脚本的提示信息
parser = argparse.ArgumentParser(description='一个最简单的argsparse库的使用的例子')

# help是参数的提示信息
parser.add_argument('--integer', type=int, help='一个输入的整数\n不能换行')
# 在py文件中换行
parser.add_argument(
    "--mixed_precision",
    help=(
        "Whether to use mixed precision. Choose between fp16 and bf16 (bfloat16). Bf16 requires PyTorch >="
        " 1.10.and an Nvidia Ampere GPU.  Default to the value of accelerate config of the current system or the"
        " flag passed with the `accelerate.launch` command. Use this argument to override the accelerate config."
    ),
)
args = parser.parse_args()
print('hello', args.integer)

'''
usage: t.py [-h] [--integer INTEGER] [--mixed_precision MIXED_PRECISION]

一个最简单的argsparse库的使用的例子

options:
  -h, --help            show this help message and exit
  --integer INTEGER     一个输入的整数 不能换行
  --mixed_precision MIXED_PRECISION
                        Whether to use mixed precision. Choose between fp16 and bf16 (bfloat16). Bf16 requires PyTorch >= 1.10.and an Nvidia Ampere GPU. Default to the value of accelerate
                        config of the current system or the flag passed with the `accelerate.launch` command. Use this argument to override the accelerate config.

2.3. 自动匹配前缀

唯一前缀,怎么缩短都行。注意缩到最短,是--i,不要记混成-i

>>> parser.add_argument('--integer', type=int)

>>> parser.parse_args('--integer 1'.split())
Namespace(integer=1)
>>> parser.parse_args('--integ 1'.split())
Namespace(integer=1)
>>> parser.parse_args('--in 1'.split())
Namespace(integer=1)
>>> parser.parse_args('--i 1'.split())
Namespace(integer=1)

前缀冲突

>>> parser.add_argument('--integer1', type=int)
>>> parser.add_argument('--integer2', type=int)

>>> parser.parse_args('--in 1'.split())
usage: [-h] [--integer1 INTEGER1] [--integer2 INTEGER2]
: error: ambiguous option: --in could match --integer1, --integer2
>>> parser.parse_args('--integer1 1'.split())
Namespace(integer=None, integer1=1, integer2=None)

2.4. 长短参数

# 单字母
parser.add_argument('-i', '--integer', type=int)

# 遇到重复单字母时,也可以多字母
parser.add_argument('-iF', '--inputfile', type=str)

不要把-iF(短参数的多字母)和--in(长参数的自动匹配前缀)搞混乱了。

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-i', '--integer', type=int)
parser.add_argument('-iF', '--inputfile', type=str)
args = parser.parse_args()
print('hello', args)

'''
(fff) PS E:\CodeProject\Git\rubbish> python a.py -i 1
hello Namespace(integer=1)
(fff) PS E:\CodeProject\Git\rubbish> python a.py --integer 1
hello Namespace(integer=1)
'''

2.5. type

int, float, str

parser.add_argument('a', type=int)

虽然默认 type=None, 但其实都解析为 str ,传啥都是 str 类型

>>> parser.add_argument('--k')
_StoreAction(option_strings=['--k'], dest='k', nargs=None, const=None, default=None, type=None, choices=None, required=False, help=None, metavar=None)
>>> parser.parse_args('--k None'.split())
Namespace(k='None')
>>> parser.parse_args('--k 1'.split())
Namespace(k='1')
>>> parser.parse_args('--k 1.1'.split())
Namespace(k='1.1')
>>> parser.parse_args('--k [2312]'.split())
Namespace(k='[2312]')

默认值 default=None, 是None的话就没必要再写了

>>> parser.add_argument('--a')
>>> parser.add_argument('--b', default=12)
>>> parser.parse_args(''.split())
Namespace(a=None, b=12)

bool

还用上面的写法会在False上出问题,得用action

  • store_true: 用上时值为True,不用时取默认值False
# 用上表示True,不用False
>>> parser.add_argument('--online', action='store_true')
_StoreTrueAction(option_strings=['--online'], dest='online', nargs=0, const=True, default=False, type=None, choices=None, required=False, help=None, metavar=None)
# 可以赋值默认False,效果同上
>>> parser.add_argument('--online', action='store_true', default=False)

# 出问题了,用不上和用上都是True
# parser.add_argument('--online', action='store_true', default=True)

### 必须不赋值
>>> parser.parse_args(''.split())
Namespace(online=False)
>>> parser.parse_args('--online'.split())
Namespace(online=True)

### 赋值不可以 error: unrecognized arguments: True
>>> parser.parse_args('--online True'.split())
usage: a.py [-h] [--online]
: error: unrecognized arguments: True
>>> parser.parse_args('--online False'.split())
usage: [-h] [--online]
: error: unrecognized arguments: False
  • store_false: 反向,不用是默认值True,用了False
# 正确的是
>>> parser.add_argument('--online', action='store_false')
_StoreFalseAction(option_strings=['--online'], dest='online', nargs=0, const=False, default=True, type=None, choices=None, required=False, help=None, metavar=None)
>>> parser.parse_args(''.split())
Namespace(online=True)
>>> parser.parse_args('--online'.split())
Namespace(online=False)
  • 带空格
# 用引号即可
$ python main.py --in_article "docs/virtual environment/drivers.md"
Namespace(in_article='docs/virtual environment/drivers.md')
>>> parser.add_argument('--in_article', type=str, required=True, help='Input article, relativate path')
# 问题不是引号,而是出在 split()
>>> parser.parse_args('--in_article docs/virtual environment/drivers.md'.split())
usage: [-h] --in_article IN_ARTICLE
: error: unrecognized arguments: environment/drivers.md
>>> parser.parse_args('--in_article "docs/virtual environment/drivers.md"'.split())
usage: [-h] --in_article IN_ARTICLE
: error: unrecognized arguments: environment/drivers.md"

# 所以只能手动分割
>>> parser.parse_args(['--in_article', 'docs/virtual environment/drivers.md'])
Namespace(in_article='docs/virtual environment/drivers.md')

2.6. 必选参数&可选参数

Method1: 有没有--

# 必选
>>> parser.add_argument('a', type=int)
# 可选
>>> parser.add_argument('--b', type=int)


>>> parser.parse_args('1'.split())
Namespace(a=1, b=None)
>>> parser.parse_args('1 --b=2'.split())
Namespace(b=2, a=1)

# 必须不可缺
>>> parser.parse_args(''.split())
usage: a.py [-h] [--b B] a
: error: the following arguments are required: a
# 这种方式不能加 `--`
>>> parser.parse_args('--a=1'.split())
usage: [-h] [--b B] a
: error: the following arguments are required: a

Method2:--并且required=True

# 必选
>>> parser.add_argument('--c', type=int, required=True)
# 可选
>>> parser.add_argument('--d', type=int)
>>> parser.parse_args('--c=1'.split())
Namespace(c=1, d=None)

# 同样不可或缺
>>> parser.parse_args(''.split())
usage: [-h] --c C [--d D]
: error: the following arguments are required: --c
# 这种方式必须加 --
>>> parser.parse_args('1'.split())
usage: [-h] --c C [--d D]
: error: the following arguments are required: --c

2.7. nargs

  • 不是列表:通配符 '?'

    >>> parser.add_argument('--h', nargs='?')
    >>> parser.parse_args(''.split())
    Namespace(h=None)
    >>> parser.parse_args('--h 1'.split())
    Namespace(h='1')
    
  • 列表:N(具体是正整数 1,2,3), 通配符 '+', '*'

    nargs=*,和N类似,但是没有规定列表长度。

    nargs=+,和*类似,但是给对应的项当没有传入参数时,会报错error: too few arguments。

    ######### N
    >>> parser.add_argument('--a', nargs=2) 
    >>> parser.add_argument('--b', nargs=1) 
    >>> parser.parse_args('--a 1 2 --b 3'.split())
    Namespace(a=['1', '2'], b=['3'])
    
    ######### +
    >>> parser.add_argument('--j', nargs='+')
    >>> parser.parse_args('--j 1'.split())
    Namespace(j=['1'])
    >>> parser.parse_args('--j'.split())
    : error: argument --a: expected at least one argument
    
    ######### *
    >>> parser.add_argument('--k', nargs='*')
    >>> parser.parse_args('--k 1'.split())
    Namespace(k=['1'])
    >>> parser.parse_args('--k'.split())
    Namespace(k=[])
    

    空列表[]还是None, 修改default

    # N + * 都可以
    >>> parser.add_argument('--a', nargs='+')
    >>> parser.add_argument('--b', nargs='+', default=[])
    >>> parser.parse_args(''.split())
    Namespace(a=None, b=[])
    

如果没有在命令行中出现对应的项 parser.parse_args(''.split()),则给对应的项赋值为default。特殊的是,对于可选项,如果命令行中出现了此可选项,但是之后没有跟随赋值参数 parser.parse_args('--a'.split()),则此时给此可选项并不是赋值default的值,而是赋值const的值。

const

# 可选参数的通配符,如果可选参数写了不跟参数,那么用const,而不是default
>>> parser.add_argument('--c', required=True, nargs='+') 
>>> parser.add_argument('--d', nargs='?', const='d_const', default='d_default')
>>> parser.parse_args('--c 1 --d 3'.split())
Namespace(c=['1'], d='3')
>>> parser.parse_args('--c 1 --d'.split())
Namespace(c=['1'], d='d_const')
>>> parser.parse_args('--c 1'.split())
Namespace(c=['1'], d='d_default')

2.8. 矛盾参数

group = parser.add_mutually_exclusive_group()
# group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("-v", "--verbose", action="store_true")
group.add_argument("-q", "--quiet", action="store_true")

3. action

3.1. 计数count

若default不设为0,则会有None和整数比较的异常。

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--verbosity', default=0, action='count')
args = parser.parse_args()
print('hello', args)

if args.verbosity >= 2:
    print('long long form')
elif args.verbosity >= 1:
    print('long form')
else:
    print('short form')

'''
$ python a.py
hello Namespace(verbosity=0)
short form

$ python a.py --verbosity
hello Namespace(verbosity=1)
long form

$ python a.py --verbosity --verbosity
hello Namespace(verbosity=2)
long long form
'''

3.2. 限定选项

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--level', type=int, choices=[0,1])
args = parser.parse_args()
print('hello', args)

'''
(fff) PS E:\CodeProject\Git\rubbish> python a.py 
hello Namespace(level=None)
(fff) PS E:\CodeProject\Git\rubbish> python a.py --level 0
hello Namespace(level=0)
(fff) PS E:\CodeProject\Git\rubbish> python a.py --level 1
hello Namespace(level=1)
(fff) PS E:\CodeProject\Git\rubbish> python a.py --level 12
usage: a.py [-h] [--level {0,1}]
a.py: error: argument --level: invalid choice: 12 (choose from 0, 1)
'''
# how to specify a list arg (eg. arg which has action="append")
fruit = [apple, orange, lemon]
indexes = [1, 12, 35 , 40]