argparse python模块的文档虽然非常棒,但对于我这个初学者来说,现在还难以理解。我不需要在命令行上做数学运算,也不需要在屏幕上修改格式行或更改选项字符。我想做的就是“如果arg是A,做这个,如果B做那个,如果以上都没有显示帮助并退出”。


当前回答

我对原问题的理解是双重的。首先,就最简单的argparse示例而言,我很惊讶在这里没有看到它。当然,为了简单起见,它也都是头顶上的,只有很少的电力,但它可能会让你开始。

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("a")
args = parser.parse_args()

if args.a == 'magic.name':
    print 'You nailed it!'

但是这个位置参数现在是必需的。如果在调用此程序时省略它,则会得到关于缺少参数的错误。这就引出了原问题的第二部分。Matt Wilkie似乎想要一个没有命名标签(——option标签)的可选参数。我的建议是将上面的代码修改如下:

...
parser.add_argument("a", nargs='?', default="check_string_for_empty")
...
if args.a == 'check_string_for_empty':
    print 'I can tell that no argument was given and I can deal with that here.'
elif args.a == 'magic.name':
    print 'You nailed it!'
else:
    print args.a

也许有一个更优雅的解决方案,但这是可行的,而且是极简主义的。

其他回答

注意Python HOWTOs中的Argparse教程。它从最基本的例子开始,比如这个:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
                    help="display a square of a given number")
args = parser.parse_args()
print(args.square**2)

然后发展到不那么基本的。

这里有一个预定义选项的例子,就像问的那样:

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, choices=[0, 1, 2],
                    help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbosity == 2:
    print("the square of {} equals {}".format(args.square, answer))
elif args.verbosity == 1:
    print("{}^2 == {}".format(args.square, answer))
else:
    print(answer)

最简单的答案!

附注:编写argparse文档的人是愚蠢的

python代码:

import argparse
parser = argparse.ArgumentParser(description='')
parser.add_argument('--o_dct_fname',type=str)
parser.add_argument('--tp',type=str)
parser.add_argument('--new_res_set',type=int)
args = parser.parse_args()
o_dct_fname = args.o_dct_fname
tp = args.tp
new_res_set = args.new_res_set

运行代码

python produce_result.py --o_dct_fname o_dct --tp father_child --new_res_set 1

也可以使用plac (argparse的包装器)。

作为奖励,它生成整洁的帮助说明-见下文。

示例脚本:

#!/usr/bin/env python3
def main(
    arg: ('Argument with two possible values', 'positional', None, None, ['A', 'B'])
):
    """General help for application"""
    if arg == 'A':
        print("Argument has value A")
    elif arg == 'B':
        print("Argument has value B")

if __name__ == '__main__':
    import plac
    plac.call(main)

示例输出:

没有提供参数- example.py:

usage: example.py [-h] {A,B}
example.py: error: the following arguments are required: arg

提供了意外的参数- example.py

usage: example.py [-h] {A,B}
example.py: error: argument arg: invalid choice: 'C' (choose from 'A', 'B')

提供正确的参数- example.py

Argument has value A

完整帮助菜单(自动生成)- example.py -h:

usage: example.py [-h] {A,B}

General help for application

positional arguments:
  {A,B}       Argument with two possible values

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

简短说明:

实参的名称通常等于形参名称(arg)。

arg参数后的元组注释的含义如下:

描述(有两个可能值的参数) 参数类型- 'flag', 'option'或'positional' (positional)之一 缩写(无) 参数值的类型-例如。float, string (None) 限制选项集(['A', 'B'])

文档:

要了解更多关于使用placa的知识,请查看它的伟大文档:

Plac:解析命令行的简单方法

我浏览了所有的例子和答案,但在某种程度上,它们并没有满足我的需求。所以我会给她列出一个我需要更多帮助的场景,我希望这能更好地解释这个想法。

最初的问题

我需要开发一个工具,它得到一个文件来处理它,它需要一些可选的配置文件来配置工具。

所以我需要的是以下内容

mytool.py file.text -config config-file.json

解决方案

下面是解决方案代码

import argparse

def main():
    parser = argparse.ArgumentParser(description='This example for a tool to process a file and configure the tool using a config file.')
    parser.add_argument('filename', help="Input file either text, image or video")
    # parser.add_argument('config_file', help="a JSON file to load the initial configuration ")
    # parser.add_argument('-c', '--config_file', help="a JSON file to load the initial configuration ", default='configFile.json', required=False)
    parser.add_argument('-c', '--config', default='configFile.json', dest='config_file', help="a JSON file to load the initial configuration " )
    parser.add_argument('-d', '--debug', action="store_true", help="Enable the debug mode for logging debug statements." )

    args = parser.parse_args()
    
    filename = args.filename
    configfile = args.config_file

    print("The file to be processed is", filename)
    print("The config file is", configfile)

    if args.debug:
        print("Debug mode enabled")
    else:
        print("Debug mode disabled")

    print("and all arguments are: ", args)

if __name__ == '__main__':
    main()

我将在多个增强中展示解决方案,以展示其思想

第一轮:列出论点

将所有输入列为强制输入,因此第二个参数为

parser.add_argument('config_file', help="a JSON file to load the initial configuration ")

当我们获得该工具的帮助命令时,会发现以下结果

(base) > python .\argparser_example.py -h
usage: argparser_example.py [-h] filename config_file

This example for a tool to process a file and configure the tool using a config file.

positional arguments:
  filename     Input file either text, image or video
  config_file  a JSON file to load the initial configuration

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

当我像下面这样执行它时

(base) > python .\argparser_example.py filename.txt configfile.json

结果将是

The file to be processed is filename.txt
The config file is configfile.json
and all arguments are:  Namespace(config_file='configfile.json', filename='filename.txt')

但是配置文件应该是可选的,我从参数中删除了它

(base) > python .\argparser_example.py filename.txt

结果将是:

usage: argparser_example.py [-h] filename config_file
argparser_example.py: error: the following arguments are required: c

也就是说我们的工具有问题

第二轮:优化

因此,为了使它成为可选的,我修改了程序如下

    parser.add_argument('-c', '--config', help="a JSON file to load the initial configuration ", default='configFile.json', required=False)

帮助的结果应该是

usage: argparser_example.py [-h] [-c CONFIG] filename

This example for a tool to process a file and configure the tool using a config file.

positional arguments:
  filename              Input file either text, image or video

optional arguments:
  -h, --help            show this help message and exit
  -c CONFIG, --config CONFIG
                        a JSON file to load the initial configuration

所以当我执行程序时

(base) > python .\argparser_example.py filename.txt

结果将是

The file to be processed is filename.txt
The config file is configFile.json
and all arguments are:  Namespace(config_file='configFile.json', filename='filename.txt')

有这样的论点

(base) > python .\argparser_example.py filename.txt --config_file anotherConfig.json

结果将是

The file to be processed is filename.txt
The config file is anotherConfig.json
and all arguments are:  Namespace(config_file='anotherConfig.json', filename='filename.txt')

第三轮:增强

要将标志名从——config_file更改为——config,同时保持变量名不变,我们修改代码,包括dest='config_file',如下所示:

parser.add_argument('-c', '--config', help="a JSON file to load the initial configuration ", default='configFile.json', dest='config_file')

命令是

(base) > python .\argparser_example.py filename.txt --config anotherConfig.json

为了增加对调试模式标志的支持,我们需要在参数中添加一个标志来支持布尔调试标志。为了实现它,我添加了以下内容:

    parser.add_argument('-d', '--debug', action="store_true", help="Enable the debug mode for logging debug statements." )

工具命令如下:

(carnd-term1-38) > python .\argparser_example.py image.jpg -c imageConfig,json --debug

结果将是

The file to be processed is image.jpg
The config file is imageConfig,json
Debug mode enabled
and all arguments are:  Namespace(config_file='imageConfig,json', debug=True, filename='image.jpg')

Matt正在询问argparse中的位置参数,我同意Python文档在这方面是缺乏的。在大约20多页的文章中,没有一个完整的例子同时展示了解析和使用位置参数。

这里的其他答案都没有显示位置参数的完整示例,所以这里有一个完整的示例:

# tested with python 2.7.1
import argparse

parser = argparse.ArgumentParser(description="An argparse example")

parser.add_argument('action', help='The action to take (e.g. install, remove, etc.)')
parser.add_argument('foo-bar', help='Hyphens are cumbersome in positional arguments')

args = parser.parse_args()

if args.action == "install":
    print("You asked for installation")
else:
    print("You asked for something other than installation")

# The following do not work:
# print(args.foo-bar)
# print(args.foo_bar)

# But this works:
print(getattr(args, 'foo-bar'))

让我困惑的是argparse将命名参数“——foo-bar”转换为“foo_bar”,但是名为“foo-bar”的位置参数仍然是“foo-bar”,这使得在程序中如何使用它变得不那么明显。

注意示例末尾的两行——这两行都不能获取foo-bar位置参数的值。第一个显然是错误的(它是一个算术表达式。Foo - bar),但第二个也不行:

AttributeError: 'Namespace' object has no attribute 'foo_bar'

如果希望使用foo-bar属性,必须使用getattr,如示例的最后一行所示。疯狂的是,如果你试图使用dest=foo_bar将属性名更改为更容易访问的名称,你会得到一个非常奇怪的错误消息:

ValueError: dest supplied twice for positional argument

下面是上面例子的运行方式:

$ python test.py
usage: test.py [-h] action foo-bar
test.py: error: too few arguments

$ python test.py -h
usage: test.py [-h] action foo-bar

An argparse example

positional arguments:
  action      The action to take (e.g. install, remove, etc.)
  foo-bar     Hyphens are cumbersome in positional arguments

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

$ python test.py install foo
You asked for installation
foo