python命令行参数解析模块argparse和docopt

http://blog.csdn.net/pipisorry/article/details/53046471

参数解析模块argparse

添加命令行解析参数add_argument()方法

参数可以触发不同的动作,动作由 add_argument() 方法的 action 参数指定。支持的动作包括保存参数(逐个地,或者作为列表的一部分),当解析到某参数时保存一个常量值(包括对布尔开关真/假值的特殊处理),统计某个参数出现的次数,以及调用一个回调函数。

默认的动作是保存参数值。在这种情况下,如果提供一个类型,那么在存储之前会先把该参数值转换成该类型。如果提供 dest 参数,参数值就保存为命令行参数解析时返回的命名空间对象中名为该 dest 参数值的一个属性。

add_argument参数

ArgumentParser.add_argument(name or flags...[, action][, nargs][, const][, default][, type][, choices][, required][, help][, metavar][, dest])

Define how a single command-line argument should be parsed. Each parameterhas its own more detailed description below, but in short they are:

  • name or flags - Either a name or a list of option strings, e.g. fooor -f, --foo.
  • action - The basic type of action to be taken when this argument isencountered at the command line.
  • nargs - The number of command-line arguments that should be consumed.
  • const - A constant value required by some action and nargs selections.
  • default - The value produced if the argument is absent from thecommand line.对于可选参数,default的值用于选项字符串没有出现在命令行中的时候。
  • type - The type to which the command-line argument should be converted.默认字符串。
  • choices - A container of the allowable values for the argument.
  • required - Whether or not the command-line option may be omitted(optionals only).
  • help - A brief description of what the argument does.
  • metavar - A name for the argument in usage messages.
  • dest - The name of the attribute to be added to the object returned byparse_args().

[add_argument() method]

参数:动作action:

argparse内置6种动作可以在解析到一个参数时进行触发:

store 保存参数值,可能会先将参数值转换成另一个数据类型。若没有显式指定动作,默认为此模式,存储值到指定变量。如果没有指定值,则值为None。

store_const 保存一个被定义为参数规格一部分的值,而不是一个来自参数解析而来的值。这通常用于实现非布尔值的命令行标记。lz:使用const='value-to-store'来保存默认值(如果没有指定值的话)?

store_ture/store_false 这两个动作被用于实现布尔开关,保存对应参数为布尔值。其中action='store_true'表示如果存在这个参数则默认为True(即使default =False),如果不存在这个参数使用default。action='store_false',表示如果存在这个参数则默认为False(即使default =True),如果不存在这个参数使用default,定义有点奇怪最好不要用。

append 将值保存到一个列表中。若参数重复出现,则保存多个值。存储值到列表,该参数可以重复使用。

append_const 将一个定义在参数规格中的值保存到一个列表中。设不设置default=[]好像没影响。也是使用const='value-2-to-append',添加默认值。

version 打印关于程序的版本信息,然后退出

示例

示例1

parser.add_argument("--data", default=None, required=True, type=str, help="数据文件夹")
parser.add_argument("--do_train", action='store_true', help="是否进行训练")
parser.add_argument("--cuda_ids", default="0,1,2,3", type=str, help="0,1,2,3")
parser.add_argument("--epoch_num", default=20, type=int, help="epoch")
parser.add_argument("--lr", default=1e-3, type=float, help="learning rate")

示例2

以下简单示例带有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']))
# Namespace(a=True, b='val', c=3)

有几种方式传递值给单字符选项。以上例子使用了两种不同的形式,-bval-c val

可变形参列表nargs

你可以配置单个参数的定义使其能够匹配所解析的命令行的多个参数。根据需要或期望的参数个数,设置nargs为这些标识值之一:

值  含义
N   参数的绝对个数(例如:3)
?   0或1个参数
*   0或所有参数
+   所有,并且至少一个参数

parser.add_argument('--all', nargs='*', dest='all')

parser.add_argument('-o', nargs=3)

绝对个数不能是字符串'3',否则报错:ValueError: length of metavar tuple does not match nargs

参数类型type

argparse将所有参数值都看作是字符串,除非你告诉它将字符串转换成另一种数据类型。add_argument()的type参数以一个转换函数作为值,被ArgumentParser用来将参数值从一个字符串转换成另一种数据类型。

参数类型type:如果不指定参数类型,argparse默认它是字符串。

parser.add_argument('--file', type=file)
try:
    print parser.parse_args()
except IOError, msg:
    parser.error(str(msg))

文件参数

虽然文件对象可以单个字符串参数值来实例化,但并不允许你指定访问模式。FileType让你能够更加灵活地指定某个参数应该是个文件,包括其访问模式和缓冲区大小。

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

如何直接解析-a True/-a False为bool

解析-a False时,无论是
parser.add_argument('-a', action='store_true', default=False) #只要存在-a就是True
parser.add_argument('-a', type=bool, default=False) #bool('False')还是True
得到的a都是True
解决:

from distutils.util import strtobool
parser.add_argument("-a", required=False, type=lambda x:bool(strtobool(x)), default=False)

distutils.util.strtobool(val): Convert a string representation of truth to true (1) or false (0).True values are y, yes, t, true, on and 1(其实还有True\False\FALSE等); false values are n, no, f, false, off and 0. Raises ValueError if val is anything else.

[Converting from a string to boolean in Python?][用argparse解析布尔值]

参数预定义值choice

将一个输入参数限制为一个预定义集中的某个值,则使用choices参数。

parser.add_argument('--mode', choices=('read-only', 'read-write'))
如果--mode的参数值不是所允许的值中的一个,就会产生一个错误并停止执行。

自动生成选项-h -v

经过配置argparse会自动添加选项用来生成帮助信息以及为你的应用程序显示版本信息。
ArgumentParser的参数add_help 控制帮助信息相关的选项。
parser = argparse.ArgumentParser(add_help=True)
帮助选项(-h和--help)默认是添加的,但可以通过将add_help设置为false来禁用。
虽然-h和--help是事实上的请求帮助的标准选项名称,但一些应用或argparse的使用要么不需要提供帮助要么需要将这两个选项名称用于其他目标。

当在ArgumentParser构造方法设置版本后,就会添加版本选项(-v和--version)。
parser = argparse.ArgumentParser(version='1.0')
两种形式的选项爱那个都会打印程序的版本字符串,然后立即退出程序。

自定义动作

除了前面描述的内置动作之外,你也可以提供一个实现了Action API的对象来自定义动作。作为action传递给add_argument()的对象应接受描述所定义形参的实参,并返回一个可调用对象,作为parser的实参来处理形参,namespace存放解析的结果、参数值,以及触发动作的option_string。
argparse提供了一个Action类作为要定义的新动作的基类。构造方法是处理参数定义的,所以你只要在子类中覆盖call()。

自定义action是argparse.Action的子类可以处理add_argument中的参数定义相关的参数,并返回一个可调用对象。构造函数会处理参数定义,仅仅需要处理__call__函数。__call__函数中parser代表解释器,namespace用于返回解释结果,value为要处理的参数,option_string用于触发action(对可选参数,永远是None。

非选项参数值的处理

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

解析器组

共享解析器规则
冲突的选项
参数群组
互斥选项
嵌套解析器

。。。

皮皮blog

ArgumentParser对象

选项前缀prefix_chars

argparse选项的默认语法是基于Unix约定的,使用一个“-”前缀来表示命令行开关。argparse支持其他前缀,因此你可以使得你的程序遵照本地平台的默认语法(例如,在Window上使用“/”)或者遵循不同的约定。

将ArgumentParser 方法的prefix_chars 参数设置为一个字符串,该字符串包含所有允许用来表示选项的字符。需要理解的是虽然prefix_chars包含允许用于开关的字符,但单个参数定义只能使用一种给定的开关语法。这让你可以对使用不同前缀的选项是否是别名(比如独立于平台的命令行语法的情况)或替代选择(例如,使用“+”表明打开一个开发,“-”则为关闭一个开关)进行显式地控制。在上述例子中,+a和-a是不同的参数,//noarg 也可以 ++noarg 提供,但不是 --noarg。

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

argparse异常处理

argparse出错异常时总是输出,而有时我们只需要不出现异常的解析结果,异常的直接丢掉。这时我们可以自定义一个error输出。

parser.error = lambda errmsg: exec('raise(Exception(errmsg))')

再在外层处理

try:
    args = vars(parser.parse_args(s.split()[1:]))
except Exception as  e:
    # print('{} has invalid args!!!\n{}\n'.format(s, traceback.format_exc()))
    print('{} has invalid args!!!\n{}\n'.format(s, e))
    return

[Python argparse and controlling/overriding the exit status code]

[I want Python argparse to throw an exception rather than usage]

[ArgumentParser objects]

皮皮blog

parse_args()方法

解析一个命令行参数来源parse_args()

定义了所有参数之后,你就可以给 parse_args() 传递一组参数字符串来解析命令行。默认情况下,参数是从 sys.argv[1:] 中获取,但你也可以传递自己的参数列表。选项是使用GNU/POSIX语法来处理的,所以在序列中选项和参数值可以混合。parse_args() 的返回值是一个命名空间,包含传递给命令的参数。该对象将参数保存其属性,因此如果你的参数 dest 是 "myoption",那么你就可以args.myoption 来访问该值。

目前为止所见的例子中,提供给解析器的参数列表来自于显式传递的一个列表,或隐式地从sys.argv获取的。显式传递列表在你使用argparse来处理类命令行但并不是来自命令行(比如来自一个配置文件)的指令之时比较有用。

1

import shlex

argument_list = shlex.split(config_value)
print 'Results:', parser.parse_args(argument_list)

2

另一种自己处理配置文件的方法是使用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'])
该示例代码在找到一个以@为前缀的参数时即停止往下读取,然后从以该参数命名的文件中查找更多的参数。...

[The parse_args() method]

使用示例

示例1

如果想直接在代码中加参数,可以这样
sys.argv += ['--original_data_dir', '../../data', '--tokenized_dir', '../../data/tokenized_dir']

示例2

def t():
    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='t', help='Set a switch to true')
    parser.add_argument('-f', action='store_false', default=False, dest='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',
                        help='Add different values to list')
    parser.add_argument('-B', action='append_const', dest='const_collection', const='value-2-to-append',default=[],
                        help='Add different values to list')
    parser.add_argument('--version', action='version', version='%(prog)s 1.0')

    # results = parser.parse_args('-a dk -a di -f -B -A'.split())
    results = parser.parse_args()
    print('simple_value     =', results.simple_value)
    print('constant_value   =', results.constant_value)
    print('t   =', results.t)
    print('f   =', results.f)
    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']

示例3:解析参数并修改,不符合的删除(代码非最优)

origin_strs = [
    '#/bin/clang -g  -DUNDEF_THREADS_HACK -c -o chared_err.o chared.c',
    '#/bin/clang -g  -DUNDEF_THREADS_HACK -c -o aa chared_err.o chared.c']


def argparse_test(s):
    import argparse, re, os, traceback
    dir = 'path'

    parser = argparse.ArgumentParser(description='Process clang args')
    parser.error = lambda errmsg: exec('raise(Exception(errmsg))')

    parameters = ['-g', '-DUNDEF_THREADS_HACK', '-c', '-o']
    parser.add_argument(parameters[0], dest=parameters[0], action='store_true', required=True)
    parser.add_argument(parameters[1], dest=parameters[1], action='store_true', required=True)
    parser.add_argument(parameters[2], dest=parameters[2], action='store_true', required=True)
    parser.add_argument(parameters[3], dest=parameters[3], nargs=2)

    try:
        args = vars(parser.parse_args(s.split()[1:]))
    except Exception as  e:
        # print('{} has invalid args!!!\n{}\n'.format(s, traceback.format_exc()))
        print('{} has invalid args!!!\n{}\n'.format(s, e))
        return
    new_str = s.split()[0]
    for p in parameters:
        if args.get(p):
            if type(args.get(p)) is list:
                args[p] = ' '.join(args.get(p))
            if p is '-c':
                args[p] = ' -emit-llvm -c'
            elif p is '-o':
                args[p] = ' -o ' + re.sub('(\w+\.o)', os.path.join(dir, r'\1') + '.bc', args[p])
            else:
                args[p] = ' '.join([p, args.get(p)]) if type(args.get(p)) is not bool else ' ' + p
            new_str += args.get(p)

    print("{} \n ====> \n {}\n".format(s, new_str))

for s in origin_strs:
    argparse_test(s)

如果有输入参数,又有parser = argparse.ArgumentParser().parse_args(),但是输入的参数未注册,就会出错:error: unrecognized arguments。 

应该可以通过下面parse_known_args解决。

parse_known_args()方法

用法:

args, extra_flags = parser.parse_known_args()

针对parse_args解析时,如果命令比add_argument()的多了一个参数会报错的问题。

parse_known_args()返回的是一个有两个元素的元组,第一个元素是NameSpace,和parge_args()返回的NameSpace完全相同;第二个是一个空列表。
如果在终端输入下面的命令并执行:
python test.py --flag_int 3 --flag_float 0.3
可以看到命令比add_argument()的多了一个参数,但是并没有报错,输出结果如下:
(Namespace(flag_int=3), ['--flag_float', '0.3'])
Namespace(flag_int=3)
['--flag_float', '0.3']
可以看出,相对于上一条命令多余的东西,以空格为分节符,以字符串的形式存放在列表中。

[parse_args()和parse_known_args()的用法和区别]

argparse.Namespace()对象

args = argparse.ArgumentParser().parse_args()返回的args是一个argparse.Namespace()。
如果只想用这个对象指定并保存参数,可以这样:
args = argparse.Namespace()
args.abc = 'abc'

皮皮blog

其它参数解析模块

直接的命令行参数读取

$ python test.py arg1 arg2 arg3

Python 中也可以所用 sys 的 sys.argv 来获取命令行参数:

  • sys.argv 是命令行参数列表。

  • len(sys.argv) 是命令行参数个数。

注:sys.argv[0] 表示脚本名。

还有其他两个模块实现这一功能,getopt(等同于C语言中的getopt())和弃用的optparse。因为argparse是基于optparse,所以用法很类似。

参数解析模块docopt

Pythonic的命令行参数解析库。 docopt : Pythonic command line arguments parser, that will make you smile. docopt,替代argparse,简洁明快。最关键的是它的思路完全不同。Github: https://github.com/docopt/docopt

用过doctest? 那来看看docopt。有时候你用py写一个命令行程序,需要接收命令行参数,看看这个例子:

"""
Usage: test.py <file> [--verbose]
"""
from docopt import docopt
print docopt(__doc__)

如果你这么执行程序 python test.py somefile --verbose

你会得到这样的输出 {'--verbose': True, '<file>': 'somefile'}

"""Usage:
  quick_example.py tcp <host> <port> [--timeout=<seconds>]
  quick_example.py serial <port> [--baud=9600] [--timeout=<seconds>]
  quick_example.py -h | --help | --version

"""

[英文文档docopt Command-line interface description language]

皮皮blog

clize

用 docopt 写程序的使用doc是不是很爽, clize是一个类似的库。可以用程序的函数名字来作为使用方法

#!/usr/bin/env python

from clize import clize

@clize
def echo(text, reverse=false):
    if reverse:
        text = text[::-1]
    print(text)
if __name__ == '__main__':
    import sys
    echo(*sys.argv)

而这个小程序就可以这么使用:

$ ./echo.py --help
Usage: ./echo.py [OPTIONS] text

Positional arguments:
  text

Options:
  --reverse
  -h, --help   Show this help

[https://github.com/epsy/clize]

from: python命令行参数解析模块argparse和docopt_皮皮blog-CSDN博客

ref: [argparse — Parser for command-line options, arguments and sub-commands]

[Argparse简易教程译自Argparse Tutorial]

[argparse - 命令行选项与参数解析(译)*]

### 回答1: `parser.add_argument` 是 Python argparse的一个方法,它的作用是向命令行程序的参数解析器添加参数。 常用的参数有: - `dest`:将该参数存储为命名属性。 - `type`:该参数的数据类型。 - `default`:该参数的默认值。 - `help`:该参数的帮助信息。 - `required`:该参数是否为必需参数。 - `choices`:该参数的可选值列表。 - `metavar`:在帮助信息显示的该参数的名称。 - `action`:该参数的操作。 例如: ``` parser.add_argument("--input", type=str, help="input file", required=True) parser.add_argument("--output", type=str, help="output file", default="output.txt") ``` ### 回答2: parser.add_argument参数用于在命令行解析和定义需要输入的参数。在Python,我们可以使用argparse库来创建一个参数解析器(Parser)。这个参数解析器负责解析命令行输入的参数,并将其转换为Python可用的数据类型,以便我们可以在程序使用这些参数。 使用parser.add_argument函数,我们可以依次添加需要解析参数。该函数的参数如下: - name/flags:参数的名称或选项标志。可以是一个字符串,例如"input_file",或者是一个由多个短选项组成的元组,例如("-i", "--input_file")。这个参数是必需的。 - action:参数的动作,默认是"store",将输入的值保存下来,我们可以在程序使用。还可以选择其他的动作,比如"store_true",将参数设置为True;"store_false",将参数设置为False;"append",将参数保存为列表等。 - type:参数的数据类型,默认是字符串。例如,如果我们想将参数解析为整数,可以将type设置为int。 - default:参数的默认值。如果没有在命令行输入参数,将使用默认值。 - help:参数的帮助信息,当我们运行程序时,可以通过命令行参数'--help'查看帮助信息。 使用parser.add_argument,我们可以定义程序需要接收的命令行参数的各种属性,包括名称、类型、默认值等。在程序,我们可以通过解析解析命令行参数并获取这些参数的值,以便进行后续的处理。这使得我们能够更加灵活和方便地从命令行传入参数,提高了程序的可扩展性和互动性。 ### 回答3: parser.add_argument是Pythonargparse模块提供的一个方法,用于解析命令行参数。这个方法可以用来定义需要从命令行接收的参数,并对其进行验证。它的主要作用是将命令行提供的参数解析Python的对象,方便程序进行后续的处理。 parser.add_argument方法接受不同的参数来定义需要接收的命令行参数。常用的参数类型包括位置参数(positional arguments)和可选参数optional arguments)。位置参数是指命令行不带任何标记的参数,而可选参数则需要使用标记来指定。 位置参数可以通过设置参数名、描述、类型和默认值等属性来定义,这可以使程序在解析参数时对位置参数进行验证,并将其转换为正确的类型。可选参数的定义需要设置要接受的标志名、描述、类型和默认值等属性。 使用parser.add_argument方法定义的参数还可以指定其他的属性,如nargs表示参数的个数,choices表示参数的取值范围,help表示参数的帮助信息等。这些属性可以进一步提高参数的灵活性和可控性。 在应用程序,一旦使用parser.add_argument方法定义了需要接收的参数,就可以通过调用parser.parse_args()方法将命令行参数解析为一个对象。这个对象包含了所有已解析参数及其对应的值。程序可以直接使用这个对象来获取和处理命令行参数,从而实现根据不同的参数执行不同的操作。 综上所述,parser.add_argument方法是Pythonargparse模块用于解析命令行参数的一个重要方法。通过定义参数的名称、描述、类型和默认值等属性,程序可以方便地接收、验证和处理命令行参数,增加程序的灵活性和可控性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值