简单的argparse示例:1个参数,3个结果

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

410018 次浏览

以下是我使用argparse(带多个参数)的方法:

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

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

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函数为参数创建字典结构,如果这样可以使您的工作更轻松的话。

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

如您所见,vars返回一个dict,其中参数名称为键,其值为,呃,值。

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

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

补充一下其他人已经说过的话:

我通常喜欢使用'dest'参数指定变量名,然后使用'globals().update()'将这些变量放在全局命名空间中。

用法:

$ python script.py -i "Hello, World!"

代码:

...
parser.add_argument('-i', '--input', ..., dest='inputted_variable',...)
globals().update(vars(parser.parse_args()))
...
print(inputted_variable) # Prints "Hello, World!"

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

以下是我在学习项目中想到的,主要感谢@DMH…

演示代码:

import argparse


def main():
parser = argparse.ArgumentParser()
parser.add_argument('-f', '--flag', action='store_true', default=False)  # can 'store_false' for no-xxx flags
parser.add_argument('-r', '--reqd', required=True)
parser.add_argument('-o', '--opt', default='fallback')
parser.add_argument('arg', nargs='*') # use '+' for 1 or more args (instead of 0 or more)
parsed = parser.parse_args()
# NOTE: args with '-' have it replaced with '_'
print('Result:',  vars(parsed))
print('parsed.reqd:', parsed.reqd)


if __name__ == "__main__":
main()

这可能已经发展,可以在网上获得:command-line.py

脚本来测试这段代码:command-line-demo.sh

您也可以使用温馨的(围绕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)

示例输出:

# EYZ1 # EYZ0:

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

# EYZ1 # EYZ0:

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

# eyz1 # eyz0:

Argument has value A

# EYZ1 # EYZ0:

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后的元组注释的含义如下:

  • 描述(# EYZ0)
  • 参数类型- 'flag', 'option'或'positional'之一(positional)
  • 缩写(# EYZ0)
  • 参数值的类型-例如。float, string (None)
  • 有限的选择集(['A', 'B'])

文档:

要了解更多关于使用温馨的的信息,请查看它的出色文档:

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

另一个总结介绍,灵感来自这篇文章

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时,这个参数的描述。
  • 默认的:省略参数时的默认值。
  • 类型:如果你期望一个floatint(否则是str)。
  • 桌子:给标志一个不同的名字(例如'-x', '--long-name', dest='longName')。< br > # EYZ4
  • 行动:用于特殊处理某些参数
    • # EYZ0:为布尔参数
      '--foo', action='store_true' => args.foo == True
    • # EYZ0:与选项const
      '--foo', action='store_const', const=42 => args.foo == 42一起使用
    • # EYZ0:用于重复选项,如./myscript.py -vv
      '-v', action='count' => args.v == 2
    • # EYZ0:用于重复选项,如./myscript.py --foo 1 --foo 2
      '--foo', action='append' => args.foo == ['1', '2']
    • 李< / ul > < / >
    • 要求:如果一个标志是必需的,或者一个位置参数不是。
    • 娜戈:一个标志捕获N个参数
      ./myscript.py --foo a b => args.foo = ['a', 'b']
    • 选择:限制可能的输入(指定为字符串列表,如果是type=int则指定为整数)。

使用argparse和修改'-h'/ '——help'开关来显示你自己的个人代码帮助指令的一个非常简单的方法是将默认帮助设置为False,你也可以添加尽可能多的额外的.add_arguments:

import argparse


parser = argparse.ArgumentParser(add_help=False)


parser.add_argument('-h', '--help', action='help',
help='To run this script please provide two arguments')
parser.parse_args()

执行命令python test.py -h

输出:

usage: test.py [-h]


optional arguments:
-h, --help  To run this script please provide two arguments

最简单的答案!

附注:编写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

由于你没有澄清参数“A”和“B”是位置的还是可选的,我将两者混合。

默认情况下,位置参数是必需的。如果没有给出一个将抛出'Few arguments given'这不是可选参数的情况下,以他们的名字。默认情况下,此程序将接受一个数字并返回其方框,如果使用cube选项,则将返回其方框。

import argparse
parser = argparse.ArgumentParser('number-game')
parser.add_argument(
"number",
type=int,
help="enter a number"
)
parser.add_argument(
"-c", "--choice",
choices=['square','cube'],
help="choose what you need to do with the number"
)


# all the results will be parsed by the parser and stored in args
args = parser.parse_args()


# if square is selected return the square, same for cube
if args.c == 'square':
print("{} is the result".format(args.number**2))
elif args.c == 'cube':
print("{} is the result".format(args.number**3))
else:
print("{} is not changed".format(args.number))

使用

$python3 script.py 4 -c square
16

这里的可选参数是有值的,如果你只是想把它当作一个标志来使用,你也可以。因此,通过使用-s表示正方形,使用-c表示立方体,我们可以通过添加action = "store_true"来改变行为。仅在使用时才更改为true。

parser.add_argument(
"-s", "--square",
help="returns the square of number",
action="store_true"
)
parser.add_argument(
"-c", "--cube",
help="returns the cube of number",
action="store_true"
)

所以条件块可以更改为,

if args.s:
print("{} is the result".format(args.number**2))
elif args.c:
print("{} is the result".format(args.number**3))
else:
print("{} is not changed".format(args.number))

使用

$python3 script.py 4 -c
64

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

最初的问题

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

所以我需要的是以下内容

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

代码文件:argparseDemo.py

简单:普通情况

  • name(abbr, full), with help
    import argparse
    
    
    argParser = argparse.ArgumentParser()
    argParser.add_argument("-n", "--name", help="your name")
    
    
    args = argParser.parse_args()
    print("args=%s" % args)
    
    
    print("args.name=%s" % args.name)
    
      <李>调用
      • # EYZ0
      • # EYZ0
    • 输出:args=Namespace(name='Crifan')args.name=Crifan
  • <李>类型
    argParser.add_argument("-a", "--age", type=int, help="your current age")
    print("type(args.age)=%s" % type(args.age))
    
    • 电话:# EYZ0
    • 输出:type(args.age)=<class 'int'>args.age=30
    <李>要求
    argParser.add_argument("-a", "--age", required=True, type=int, help="your current age")
    
    • 电话:# EYZ0
    • 输出:错误argparseDemo.py: error: the following arguments are required: -a/--age
    <李>默认
    argParser.add_argument("-a", "--age", type=int, default=20, help="your current age. Default is 20")
    
    • 电话:# EYZ0
    • 输出:# EYZ0
    <李>选择
    argParser.add_argument("-f", "--love-fruit", choices=['apple', 'orange', 'banana'], help="your love fruits")
    
    • 电话:# EYZ0
    • 输出:args=Namespace(love_fruit='apple')args.love_fruit=apple
    <李>多参数
    argParser.add_argument("-f", "--love-fruit", nargs=2, help="your love fruits")
    
    • 电话:# EYZ0
    • 输出:# EYZ0

细节

最简单的:-x

  • < p >代码:

    import argparse
    
    
    argParser = argparse.ArgumentParser()
    argParser.add_argument("-a") # most simple -> got args.a, type is `str`
    args = argParser.parse_args()
    
    
    print("args.a=%s" % args.a)
    
  • usage =在命令行中运行

    python argparseDemo.py -a 30
    
      <李>或:# EYZ0
      • makesure argparseDemo.py是可执行的
        • 如果没有,添加:chmod +x argparseDemo.py
  • < p >输出

    args.a=30
    
  • < p >注意

    • 默认类型为str
      • # eyz0 == # eyz1
      • # EYZ0→# EYZ1
    • args类型为Namespace
      • # EYZ0→# EYZ1
    • args值为Namespace(a='30')
      • # EYZ0→# EYZ1
      • 所以我们可以调用/使用args.a

参数名称

完整参数名:--xxx

    <李>代码
    argParser.add_argument("-a", "--age")
    
    <李>用法
      <李> # EYZ0
      • 或:# EYZ0
  • get解析值:args.age
    • 注: args.a不存在 args.a

包含多个单词的完整参数名:--xxx-yyy

    <李>代码
    argParser.add_argument("-a", "--current-age")
    
  • current_age . get解析值:args

添加帮助描述:help

    <李>代码
    argParser.add_argument("-a", help="your age") # with help
    
    <李>输出
    • 使用--help可以看到描述
       python argparseDemo.py --help
      usage: argparseDemo.py [-h] [-a A]
      
      
      optional arguments:
      -h, --help  show this help message and exit
      -a A        your age
      

指定参数类型:type

    <李>代码
    argParser.add_argument("-a", type=int) # parsed arg is `int`, not default `str`
    
    <李>输出
    • # EYZ0→# EYZ1
    • # EYZ0→# EYZ1

添加默认值:default

    <李>代码
    argParser.add_argument("-a", type=int, default=20) # if not pass a, a use default value: 20
    
    <李>效果
    • 用法:# EYZ0
    • 输出:print("args.age=%s" % args.age) -># EYZ1

这是一个新手,但是将Python与Powershell结合起来,并使用这个模板,受到深入而伟大的Python命令行参数-真正的Python的启发

init_argparse()中可以做很多事情,这里我只介绍最简单的场景。

  1. # EYZ0
  2. 使用if __name__ == "__main__": main()模式从终端执行
  3. 解析没有形参的main()函数中的参数
  4. 定义一个init_argparse()函数
    • 通过调用argparse.ArgumentParser()创建解析器对象
    • 使用parser.add_argument("--<long_param_name>")声明一个或多个参数
    • 返回解析器
  5. 通过调用parser.parse_args()创建args对象来解析参数
  6. param1param2,…定义一个函数
  7. 调用function_proper,参数被赋值为args对象的属性
    • 例如:# EYZ0
  8. 在shell中调用带有命名参数的模块:
    • 例如:# EYZ0
#file: foobar.py
import argparse


def function_proper(param1, param2):
#CODE...


def init_argparse() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser()
parser.add_argument("--param1")
parser.add_argument("--param2")
return parser




def main() -> None:
parser = init_argparse()
args = parser.parse_args()
function_proper(param1=args.param1, param2=args.param2)




if __name__ == "__main__":
main()
>>> python .\foobar.py --param1="foo" --param2=="bar"

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

# EYZ0:

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

# EYZ0:

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

# EYZ0:

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:正如规则中提到的,我必须指定这是我自己的项目

代码:

import argparse
parser=argparse.ArgumentParser()
parser.add_argument('-A', default=False, action='store_true')
parser.add_argument('-B', default=False, action='store_true')
args=parser.parse_args()
if args.A:
print('do this')
elif args.B:
print('do that')
else:
print('help')

运行结果:

$ python3 test.py
help


$ python3 test.py -A
do this


$ python3 test.py -B
do that


$ python3 test.py -C
usage: test.py [-h] [-A] [-B]
test.py: error: unrecognized arguments: -C

对于最初的请求(如果A ....),我将使用argv来解决它,而不是使用argparse:

import sys


if len(sys.argv)==2:
if sys.argv[1] == 'A':
print('do this')
elif sys.argv[1] == 'B':
print('do that')
else:
print('help')
else:
print('help')