目录
首发于:
最近更新于:
分类: posts

argparse模块

下面简要介绍了python3的官方文档argparse模块的用法,用于快速制作一个可以刷参数的python脚本。

首先看下面这个简单的情况:

import argparse
usage = '''
this is a example to show argparse usage
'''
parser = argparse.ArgumentParser(usage=usage)

args = parser.parse_args()

这是简单的一个例子了,现在脚本还不可以接受任何参数,只可以用 -h--help 来查看一些信息,如下所示。

wanze@wanze-ubuntu64:~/桌面$ python3 hello.py -h
usage: 
this is a example to show argparse usage
 [-h]

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

其首先是新建一个parser,上面ArgumentParser的usage是可选参数,就是命令行的一些描述信息。然后需要调用parser的 parse_args 方法,其就是具体将命令行接受的一些参数刷进去。

简单添加一个参数

上面的例子太简单了,现在开始简单添加一个参数。

import argparse
usage = '''
this is a example to show argparse usage
'''
parser = argparse.ArgumentParser(usage=usage)

parser.add_argument('--config',help="the config file path")

args = parser.parse_args()

print(args)

这样命令行的帮助信息就变成如下所示了:

wanze@wanze-ubuntu64:~/桌面$ python3 hello.py -h
usage: 
this is a example to show argparse usage

optional arguments:
  -h, --help       show this help message and exit
  --config CONFIG  the config file path

如果我们如下输入则有:

wanze@wanze-ubuntu64:~/桌面$ python3 hello.py --config='config.cfg'
Namespace(config='config.cfg')

我们看到 parse_args 方法返回的是Namespace对象,推荐用 vars 函数来将其处理成为字典值,这样会更好地方便后面的使用。

import argparse
usage = '''
this is a example to show argparse usage
'''
parser = argparse.ArgumentParser(usage=usage)
parser.add_argument('-c','--config',help="the config file path")
args = vars(parser.parse_args())

print(args)

wanze@wanze-ubuntu64:~/桌面$ python3 hello.py -h
usage: 
this is a example to show argparse usage
python3 hello.py

optional arguments:
  -h, --help            show this help message and exit
  -c CONFIG, --config CONFIG
                        the config file path
wanze@wanze-ubuntu64:~/桌面$ python3 hello.py --config='config.cfg'
{'config': 'config.cfg'}

上面代码稍作修改,在长名字可选参数前面还可以加上短名字可选参数支持,然后我们看到 parse_args 方法经过 vars处理之后返回的是字典值。该字典的key默认对应的是长名字可选参数。你还可以自己设置目标参数名:

添加参数的其他选项设置

下面演示了如何设置目标参数在脚本中具体对应的变量名:

import argparse
usage = '''
this is a example to show argparse usage
'''
parser = argparse.ArgumentParser(usage=usage)
parser.add_argument('-c','--config',dest="configpath",help="the config file path")
args = vars(parser.parse_args())

print(args)

然后我们看到字典输入如下:

wanze@wanze-ubuntu64:~/桌面$ python3 hello.py --config='config.cfg'
{'configpath': 'config.cfg'}

当然一般就默认设置成为和长名字可选参数一致,没必要这么折腾。类似的你还可以继续用 add_argument 方法来添加其他的可选参数,然后 add_argument 还有如下一些选项配置:

required=True

该参数一定要输入值,否则报错

help

描述信息,前面已经看到了。

default

该参数的默认值,默认是None,你可以选择设置成另外一个值。

type

目标参数的数据类型,默认是字符串,可以设置为int或float。注意设置格式如下,不是字符串的那种设置形式: ​ parser.add_argument('--delay',type=int)

必填参数的添加如下所示,除了这个\"target\"名字前面没有 -- 之外,和可选参数用法大致类似,其刷入args字典之后的key就是\"target\"这个名字。

parser.add_argument('target',help="必填参数")

不过必填参数和可选参数在某些细节上还是有点差异的,后面会提及。

nargs选项设置

nargs设置之后该参数在脚本中具体对应的变量将是一个列表。其中nargs可以设置为一个数字,比如 nargs=4 ,则脚本对该参数将接受4个输入值,然后将其收集进一个列表里面。

此外还有:

nargs='*'

这通常是对可选参数进行设置,当然也可以作用于必填参数,但这让必填参数失去意义了。其将收集任意多的输入参数值,而如果多个可选参数之间这样使用星号是可以的,具体请参看官方文档。

nargs='+'

这通常作用于必填参数,其意义有点类似于正则表达式里面的'+'号,和上面的'*'号比起来其必须有一个输入值,否则将报错。

nargs='?'

这个'?'号具体使用情况挺复杂的,我不太喜欢,而且其和nargs其他的一些设置比较起来显得有点格格不入。首先其对应的变量值不是列表而是单个值!其次其改变了默认值的行为。如果该参数不输入,比如--foo 这个东西完全不输入在命令行里面,那么foo默认取default的值,如果加入了​ --foo 这个东西但是后面又不跟值,则foo取 const 选项赋的值。不太喜欢这个东西。

下面给出一个完整的例子:

import argparse
usage = '''
resize the image
'''

def main():
    parser = argparse.ArgumentParser(usage=usage)
    parser.add_argument('-c','--config',dest="configpath",help="the config file path")
    parser.add_argument('inputimg',help="the input image",nargs='+')
    parser.add_argument('--width',help="the input image",type=int)

    args = vars(parser.parse_args())

    configpath = args['configpath']
    width = args['width']
    inputimg = args['inputimg']

    for inputimg in args['inputimg']:
        print('resize image')
        print('the input image is {}'.format(inputimg))
        print('the target width is {}'.format(width))
if __name__ == '__main__':
    main()

具体运行情况如下所示:

wanze@wanze-ubuntu64:~/图片$ python3 resizeimg.py --help
usage: 
resize the image

positional arguments:
  inputimg              the input image

optional arguments:
  -h, --help            show this help message and exit
  -c CONFIGPATH, --config CONFIGPATH
                        the config file path
  --width WIDTH         the input image

wanze@wanze-ubuntu64:~/图片$ python3 resizeimg.py --width=300 *.png
resize image
the input image is 2015-01-27 13:16:46 的屏幕截图.png
the target width is 300
resize image
the input image is 2015-05-03 18:17:19屏幕截图.png
the target width is 300
resize image
the input image is 2015-05-03 18:20:45屏幕截图.png
the target width is 300
....

命令行选项关联其他动作

parser的 add_argument 方法的 action 参数就是用来控制命令行选项关联的动作的,一般都不需要设置,就是默认的 store ,也就是存储值。类似的有 store_const , store_truestore_false

store_const

如果是默认的store,则通常是需要指明具体值的,如果设置action为 store_const 了:

parser.add_argument('--foo', action='store_const', const=42)

那么如下就会自动设置该值,这和default默认值的区别是这个选项的值要求是某个常量值。

>> python3 test2.py --foo
Namespace(foo=42)

store_true 和 store_false

如果写为:

parser.add_argument('--foo', action='store_true')

则其存储的就是 True 值:

>> python3 test2.py --foo 
Namespace(foo=True)

这里主要是要讲定义自己的动作,就是类似 --version 这样的用法,是一种影响程序整个工作流的选项,官方文档推荐通过子类化 argparse.Action 的方法,还是有点麻烦的。然后发现 click 模块非常好(一个解决创建命令行脚本工具问题推荐使用的第三方模块),处理这个问题也很容易:

import click

def print_version(ctx, param, value):
    if not value or ctx.resilient_parsing:
        return
    click.echo('Version 1.0')
    ctx.exit()

def quick(ctx,param,value):
    print(ctx,param,value)
    ctx.exit()

@click.command()
@click.option('--version', is_flag=True, callback=print_version,
              expose_value=False, is_eager=True)
@click.option('--quick',callback=quick,is_flag=True)
def hello():
    while True:
        userinput = input('input:')
        click.echo(userinput)

        if userinput == 'exit':
            break
if __name__ == '__main__':
    hello()

这里的ctx和param到click模块那边再细讲吧,我们看到整个过程比argparse美观多了。