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


当前回答

argparse文档相当不错,但遗漏了一些可能不明显的有用细节。(@Diego Navarro已经提到了一些,但我会试着稍微扩展一下他的答案。)基本用法如下:

parser = argparse.ArgumentParser()
parser.add_argument('-f', '--my-foo', default='foobar')
parser.add_argument('-b', '--bar-value', default=3.14)
args = parser.parse_args()

从parse_args()返回的对象是一个“Namespace”对象:其成员变量以命令行参数命名的对象。Namespace对象是你访问参数和与它们相关的值的方式:

args = parser.parse_args()
print (args.my_foo)
print (args.bar_value)

(请注意,argparse在命名变量时用下划线替换参数名中的'-'。)

在许多情况下,您可能希望将参数简单地用作不带值的标志。你可以像这样在argparse中添加它们:

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

上面的代码将分别创建值为True的变量'foo'和值为False的变量'no_foo':

if (args.foo):
    print ("foo is true")

if (args.no_foo is False):
    print ("nofoo is false")

还要注意,你可以在添加参数时使用"required"选项:

parser.add_argument('-o', '--output', required=True)

这样,如果你在命令行中忽略了这个参数,argparse会告诉你它缺失了,并停止脚本的执行。

最后,请注意,可以使用vars函数创建参数的dict结构,如果这使您的生活更容易的话。

args = parser.parse_args()
argsdict = vars(args)
print (argsdict['my_foo'])
print (argsdict['bar_value'])

如你所见,vars返回一个dict,参数名作为键,值作为值。

还有许多其他选项和可以做的事情,但这应该涵盖最基本的常见使用场景。

其他回答

我对原问题的理解是双重的。首先,就最简单的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

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

这是另一个总结介绍,受这篇文章的启发。

import argparse

# define functions, classes, etc.

# executes when your script is called from the command-line
if __name__ == "__main__":

    parser = argparse.ArgumentParser()
    #
    # define each option with: parser.add_argument
    #
    args = parser.parse_args() # automatically looks at sys.argv
    #
    # access results with: args.argumentName
    #

参数由以下组合定义:

parser.add_argument( 'name', options... )              # positional argument
parser.add_argument( '-x', options... )                # single-char flag
parser.add_argument( '-x', '--long-name', options... ) # flag with long name

常见的选项有:

help: description for this arg when --help is used. default: default value if the arg is omitted. type: if you expect a float or int (otherwise is str). dest: give a different name to a flag (e.g. '-x', '--long-name', dest='longName'). Note: by default --long-name is accessed with args.long_name action: for special handling of certain arguments store_true, store_false: for boolean args '--foo', action='store_true' => args.foo == True store_const: to be used with option const '--foo', action='store_const', const=42 => args.foo == 42 count: for repeated options, as in ./myscript.py -vv '-v', action='count' => args.v == 2 append: for repeated options, as in ./myscript.py --foo 1 --foo 2 '--foo', action='append' => args.foo == ['1', '2'] required: if a flag is required, or a positional argument is not. nargs: for a flag to capture N args ./myscript.py --foo a b => args.foo = ['a', 'b'] choices: to restrict possible inputs (specify as list of strings, or ints if type=int).

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

最初的问题

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

所以我需要的是以下内容

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

下面是我使用argparse(使用多个args)的方法:

parser = argparse.ArgumentParser(description='Description of your program')
parser.add_argument('-f','--foo', help='Description for foo argument', required=True)
parser.add_argument('-b','--bar', help='Description for bar argument', required=True)
args = vars(parser.parse_args())

Args将是一个包含参数的字典:

if args['foo'] == 'Hello':
    # code here

if args['bar'] == 'World':
    # code here

在您的情况下,只需添加一个参数。

作为现有答案的补充,如果你足够懒惰,可以使用称为protoargs的代码生成工具。它从配置生成参数解析器。对于python,它使用argparse。

配置可选A和B:

syntax = "proto2";
message protoargs
{
    optional string A     = 1; // A param description
    optional string B     = 2; // B param description
}//protoargs

配置所需的A和B:

syntax = "proto2";
message protoargs
{
    required string A     = 1; // A param description
    required string B     = 2; // B param description
}//protoargs

位置A和B的构型:

syntax = "proto2";
message protoargs
{
    required string A     = 1; // A param description
    required string B     = 2; // B param description
}//protoargs
message protoargs_links
{
}//protoargs_links

现在你要做的就是:

python ./protoargs.py -i test.proto -o . --py

并使用它(这里可以举其他例子):

import sys
import test_pa

class ArgsParser:
    program = "test"
    description = "Simple A and B parser test."

    def parse(self, argv):
        self.config = test_pa.parse(self.program, self.description, argv)

    def usage(self):
        return test_pa.usage(self.program, self.description)

if __name__ == "__main__":
    parser = ArgsParser()

    if len(sys.argv) == 1:
        print(parser.usage())
    else:
        parser.parse(sys.argv[1:])

        if parser.config.A:
            print(parser.config.A)

        if parser.config.B:
            print(parser.config.B)

如果你想要更多的改变配置,重新生成解析器,使用更新的parser.config。

UPD:正如规则中提到的,我必须指定这是我自己的项目