argparse#

视频

详细介绍可以参考:

argparse:命令行选项、参数和子命令解析器

基础#

我们编写最简单的例子:

import argparse
parser = argparse.ArgumentParser()
parser.parse_args()

在没有任何选项的情况下运行脚本不会在标准输出显示任何内容。这没有什么用处:

!python examples/argparse/simple.py

--help 选项,也可缩写为 -h,是唯一一个可以直接使用的选项(即不需要指定该选项的内容):

!python examples/argparse/simple.py --help
usage: simple.py [-h]

options:
  -h, --help  show this help message and exit

指定其他任何内容都会导致错误。即便如此,我们也能直接得到一条有用的用法信息。

!python examples/argparse/simple.py --verbose
usage: simple.py [-h]
simple.py: error: unrecognized arguments: --verbose
!python examples/argparse/simple.py foo
usage: simple.py [-h]
simple.py: error: unrecognized arguments: foo

位置参数#

举个例子:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("echo")
args = parser.parse_args()
print(args.echo)

运行此程序:

!python examples/argparse/echos.py
usage: echos.py [-h] echo
echos.py: error: the following arguments are required: echo

增加了 add_argument() 方法,该方法用于指定程序能够接受哪些命令行选项。在这个例子中,我将选项命名为 echo,与其功能一致。

现在调用我们的程序必须要指定一个选项:

!python examples/argparse/echos.py foo
foo

查看帮助信息:

!python examples/argparse/echos.py -h
usage: echos.py [-h] echo

positional arguments:
  echo

options:
  -h, --help  show this help message and exit

可以给位置参数一些辅助信息:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("echo", help="echo the string you use here")
args = parser.parse_args()
print(args.echo)
!python examples/argparse/echos_help.py -h
usage: echos_help.py [-h] echo

positional arguments:
  echo        echo the string you use here

options:
  -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",
                    type=int)
args = parser.parse_args()
print(args.square**2)

以下是该代码的运行结果:

!python examples/argparse/square.py 4
16

输错类型,会触发异常:

!python examples/argparse/square.py '4'
16

当程序在收到错误的无效的输入时,它甚至能在执行计算之前先退出,还能显示很有帮助的错误信息。

可选参数#

下面看看如何添加可选参数:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--verbosity", help="increase output verbosity")
args = parser.parse_args()
if args.verbosity:
    print("verbosity turned on")

这一程序被设计为当指定 --verbosity 选项时显示某些东西,否则不显示。

!python examples/argparse/option.py --verbosity 1
verbosity turned on
!python examples/argparse/option.py

提示

如果一个可选参数没有被使用时,相关变量被赋值为 None

!python examples/argparse/option.py --help
usage: option.py [-h] [--verbosity VERBOSITY]

options:
  -h, --help            show this help message and exit
  --verbosity VERBOSITY
                        increase output 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")

现在,这一选项多了一个旗标,而非需要接受一个值的什么东西。我们甚至改变了选项的名字来符合这一思路。注意我们现在指定了一个新的关键词 action,并赋值为 "store_true"。这意味着,当这一选项存在时,为 args.verbose 赋值为 True。没有指定时则隐含地赋值为 False

!python examples/argparse/option_action.py --verbose
verbosity turned on
!python examples/argparse/option_action.py --verbose 1
usage: option_action.py [-h] [--verbose]
option_action.py: error: unrecognized arguments: 1
!python examples/argparse/option_action.py -h
usage: option_action.py [-h] [--verbose]

options:
  -h, --help  show this help message and exit
  --verbose   increase output verbosity

短选项#

例如:

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 examples/argparse/short.py -h
usage: short.py [-h] [-v]

options:
  -h, --help     show this help message and exit
  -v, --verbose  increase output verbosity
!python examples/argparse/short.py -v
verbosity turned on

结合位置参数和可选参数#

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(f"the square of {args.square} equals {answer}")
else:
    print(answer)

接着是输出:

!python examples/argparse/complex1.py
usage: complex1.py [-h] [-v] square
complex1.py: error: the following arguments are required: square
!python examples/argparse/complex1.py 4
16
!python examples/argparse/complex1.py 4 --verbose
the square of 4 equals 16

顺序无关紧要:

!python examples/argparse/complex1.py --verbose 4
the square of 4 equals 16

给程序加上接受多个 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,
                    help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbosity == 2:
    print(f"the square of {args.square} equals {answer}")
elif args.verbosity == 1:
    print(f"{args.square}^2 == {answer}")
else:
    print(answer)
!python examples/argparse/complex2.py 4
16
!python examples/argparse/complex2.py 4 -v
usage: complex2.py [-h] [-v VERBOSITY] square
complex2.py: error: argument -v/--verbosity: expected one argument
!python examples/argparse/complex2.py 4 -v 1
4^2 == 16
!python examples/argparse/complex2.py 4 -v 2
the square of 4 equals 16
!python examples/argparse/complex2.py 4 -v 3
16

作为模块使用#

# train.py
import argparse


def parse_opt(known=False):
    parser = argparse.ArgumentParser()
    opt = parser.parse_known_args()[0] if known else parser.parse_args()
    return opt


def main(opt):
    ...


def run(**kwargs):
    '''用法(来源于 yolo 代码)
    import train; train.run(data='coco128.yaml', imgsz=320, weights='yolov5m.pt')
    '''
    opt = parse_opt(True)
    for k, v in kwargs.items():
        setattr(opt, k, v)
    main(opt)


if __name__ == "__main__":
    opt = parse_opt()
    main(opt)