标签归档:argparse

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

问题:想要一个简单的argparse示例:1个参数,3个结果

文档argparse Python模块,而优秀的我敢肯定,是太多了我的小初学者的大脑现在掌握。我不需要在命令行上进行数学运算,也不需要在屏幕上设置格式行或更改选项字符。我要做的只是“如果arg是A,如果以上都不显示帮助并退出,则B这样做。”

The documentation for the argparse python module, while excellent I’m sure, is too much for my tiny beginner brain to grasp right now. I don’t need to do math on the command line or meddle with formatting lines on the screen or change option characters. All I want to do is “If arg is A, do this, if B do that, if none of the above show help and quit”.


回答 0

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

可能会有一个更优雅的解决方案,但这是可行的并且是极简主义的。

My understanding of the original question is two-fold. First, in terms of the simplest possible argparse example, I’m surprised that I haven’t seen it here. Of course, to be dead-simple, it’s also all overhead with little power, but it might get you started.

import argparse

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

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

But this positional argument is now required. If you leave it out when invoking this program, you’ll get an error about missing arguments. This leads me to the second part of the original question. Matt Wilkie seems to want a single optional argument without a named label (the –option labels). My suggestion would be to modify the code above as follows:

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

There may well be a more elegant solution, but this works and is minimalist.


回答 1

这是我的处理方式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

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

Here’s the way I do it with argparse (with multiple 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 will be a dictionary containing the arguments:

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

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

In your case simply add only one argument.


回答 2

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对象是您访问参数和与之关联的值的方式:

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

上面的代码将分别创建名称为’foo’的True变量和’no_foo’的False变量:

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,其参数名称为键,其值为er值。

您可以执行许多其他选择和操作,但这应该涵盖最基本,最常见的使用情况。

The argparse documentation is reasonably good but leaves out a few useful details which might not be obvious. (@Diego Navarro already mentioned some of this but I’ll try to expand on his answer slightly.) Basic usage is as follows:

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

The object you get back from parse_args() is a ‘Namespace’ object: An object whose member variables are named after your command-line arguments. The Namespace object is how you access your arguments and the values associated with them:

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

(Note that argparse replaces ‘-‘ in your argument names with underscores when naming the variables.)

In many situations you may wish to use arguments simply as flags which take no value. You can add those in argparse like this:

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

The above will create variables named ‘foo’ with value True, and ‘no_foo’ with value False, respectively:

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

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

Note also that you can use the “required” option when adding an argument:

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

That way if you omit this argument at the command line argparse will tell you it’s missing and stop execution of your script.

Finally, note that it’s possible to create a dict structure of your arguments using the vars function, if that makes life easier for you.

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

As you can see, vars returns a dict with your argument names as keys and their values as, er, values.

There are lots of other options and things you can do, but this should cover the most essential, common usage scenarios.


回答 3

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位置参数的值。第一个显然是错误的(这是一个算术表达式args.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

Matt is asking about positional parameters in argparse, and I agree that the Python documentation is lacking on this aspect. There’s not a single, complete example in the ~20 odd pages that shows both parsing and using positional parameters.

None of the other answers here show a complete example of positional parameters, either, so here’s a complete example:

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

The thing that threw me off is that argparse will convert the named argument “–foo-bar” into “foo_bar”, but a positional parameter named “foo-bar” stays as “foo-bar”, making it less obvious how to use it in your program.

Notice the two lines near the end of my example — neither of those will work to get the value of the foo-bar positional param. The first one is obviously wrong (it’s an arithmetic expression args.foo minus bar), but the second one doesn’t work either:

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

If you want to use the foo-bar attribute, you must use getattr, as seen in the last line of my example. What’s crazy is that if you tried to use dest=foo_bar to change the property name to something that’s easier to access, you’d get a really bizarre error message:

ValueError: dest supplied twice for positional argument

Here’s how the example above runs:

$ 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

回答 4

另一个摘要的介绍,受本文启发。

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:该参数的描述--help
  • 默认:如果省略arg的默认值。
  • 输入:如果您期望a floatint(否则为str)。
  • dest:为标志命名(例如'-x', '--long-name', dest='longName')。
    注意:默认情况下--long-name使用args.long_name
  • 动作:对某些参数的特殊处理
    • store_true, store_false用于布尔参数
      '--foo', action='store_true' => args.foo == True
    • store_const与选项一起使用const
      '--foo', action='store_const', const=42 => args.foo == 42
    • count用于重复的选项,例如./myscript.py -vv
      '-v', action='count' => args.v == 2
    • append用于重复的选项,例如./myscript.py --foo 1 --foo 2
      '--foo', action='append' => args.foo == ['1', '2']
  • required:如果需要标志,或者不需要位置参数。
  • nargs:用于捕获N args的标志
    ./myscript.py --foo a b => args.foo = ['a', 'b']
  • 选择:限制可能的输入(指定为字符串列表,如果为,则指定为int type=int)。

Yet another summary introduction, inspired by this post.

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
    #

Arguments are defined with combinations of the following:

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

Common options are:

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

回答 5

注意Argparse教程Python的HOWTO文档。它从最基本的示例开始,例如以下示例:

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)

Note the Argparse Tutorial in Python HOWTOs. It starts from most basic examples, like this one:

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)

and progresses to less basic ones.

There is an example with predefined choice for an option, like what is asked:

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)

回答 6

这主要是由于@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

Here’s what I came up with in my learning project thanks mainly to @DMH…

Demo code:

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

This may have evolved and is available online: command-line.py

Script to give this code a workout: command-line-demo.sh


回答 7

您也可以使用placargparse)。

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

示例脚本:

#!/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 C

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

提供的正确参数- example.py A

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参数之后的元组注释具有以下含义:

  • 说明(Argument with two possible values
  • 参数类型-“标志”,“选项”或“位置”(positional)之一
  • 缩写(None
  • 参数值的类型-例如 浮点数,字符串(None
  • 限制选择集(['A', 'B']

说明文件:

要了解有关使用plac的更多信息,请查看其出色的文档:

Plac:轻松解析命令行

You could also use plac (a wrapper around argparse).

As a bonus it generates neat help instructions – see below.

Example script:

#!/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 output:

No arguments supplied – example.py:

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

Unexpected argument supplied – example.py C:

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

Correct argument supplied – example.py A :

Argument has value A

Full help menu (generated automatically) – 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

Short explanation:

The name of the argument usually equals the parameter name (arg).

The tuple annotation after arg parameter has the following meaning:

  • Description (Argument with two possible values)
  • Type of argument – one of ‘flag’, ‘option’ or ‘positional’ (positional)
  • Abbreviation (None)
  • Type of argument value – eg. float, string (None)
  • Restricted set of choices (['A', 'B'])

Documentation:

To learn more about using plac check out its great documentation:

Plac: Parsing the Command Line the Easy Way


回答 8

除了其他人所说的:

我通常喜欢使用’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!"

To add to what others have stated:

I usually like to use the ‘dest’ parameter to specify a variable name and then use ‘globals().update()’ to put those variables in the global namespace.

Usage:

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

Code:

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

回答 9

使用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

A really simple way to use argparse and amend the ‘-h’/ ‘–help’ switches to display your own personal code help instructions is to set the default help to False, you can also add as many additional .add_arguments as you like:

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

Run: python test.py -h

Output:

usage: test.py [-h]

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

回答 10

最简单的答案!

PS写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

The simplest answer!

P.S. the one who wrote the document of argparse is foolish

python code:

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

running code

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

如何使用argparse将列表作为命令行参数传递?

问题:如何使用argparse将列表作为命令行参数传递?

我正在尝试将列表作为参数传递给命令行程序。是否有将argparse列表作为选项传递的选项?

parser.add_argument('-l', '--list',
                      type=list, action='store',
                      dest='list',
                      help='<Required> Set flag',
                      required=True)

脚本如下所示

python test.py -l "265340 268738 270774 270817"

I am trying to pass a list as an argument to a command line program. Is there an argparse option to pass a list as option?

parser.add_argument('-l', '--list',
                      type=list, action='store',
                      dest='list',
                      help='<Required> Set flag',
                      required=True)

Script is called like below

python test.py -l "265340 268738 270774 270817"

回答 0

TL; DR

使用nargs选项或选项的'append'设置action(取决于您希望用户界面的行为方式)。

纳尔

parser.add_argument('-l','--list', nargs='+', help='<Required> Set flag', required=True)
# Use like:
# python arg.py -l 1234 2345 3456 4567

nargs='+'接受1个或多个参数,nargs='*'接受零个或多个。

附加

parser.add_argument('-l','--list', action='append', help='<Required> Set flag', required=True)
# Use like:
# python arg.py -l 1234 -l 2345 -l 3456 -l 4567

append您提供多个选项来构建列表。

不要使用type=list-可能没有可能要与一起使用的type=list情况argparse。曾经


让我们更详细地了解人们可能尝试执行此操作的一些不同方式以及最终结果。

import argparse

parser = argparse.ArgumentParser()

# By default it will fail with multiple arguments.
parser.add_argument('--default')

# Telling the type to be a list will also fail for multiple arguments,
# but give incorrect results for a single argument.
parser.add_argument('--list-type', type=list)

# This will allow you to provide multiple arguments, but you will get
# a list of lists which is not desired.
parser.add_argument('--list-type-nargs', type=list, nargs='+')

# This is the correct way to handle accepting multiple arguments.
# '+' == 1 or more.
# '*' == 0 or more.
# '?' == 0 or 1.
# An int is an explicit number of arguments to accept.
parser.add_argument('--nargs', nargs='+')

# To make the input integers
parser.add_argument('--nargs-int-type', nargs='+', type=int)

# An alternate way to accept multiple inputs, but you must
# provide the flag once per input. Of course, you can use
# type=int here if you want.
parser.add_argument('--append-action', action='append')

# To show the results of the given option to screen.
for _, value in parser.parse_args()._get_kwargs():
    if value is not None:
        print(value)

这是您可以期望的输出:

$ python arg.py --default 1234 2345 3456 4567
...
arg.py: error: unrecognized arguments: 2345 3456 4567

$ python arg.py --list-type 1234 2345 3456 4567
...
arg.py: error: unrecognized arguments: 2345 3456 4567

$ # Quotes won't help here... 
$ python arg.py --list-type "1234 2345 3456 4567"
['1', '2', '3', '4', ' ', '2', '3', '4', '5', ' ', '3', '4', '5', '6', ' ', '4', '5', '6', '7']

$ python arg.py --list-type-nargs 1234 2345 3456 4567
[['1', '2', '3', '4'], ['2', '3', '4', '5'], ['3', '4', '5', '6'], ['4', '5', '6', '7']]

$ python arg.py --nargs 1234 2345 3456 4567
['1234', '2345', '3456', '4567']

$ python arg.py --nargs-int-type 1234 2345 3456 4567
[1234, 2345, 3456, 4567]

$ # Negative numbers are handled perfectly fine out of the box.
$ python arg.py --nargs-int-type -1234 2345 -3456 4567
[-1234, 2345, -3456, 4567]

$ python arg.py --append-action 1234 --append-action 2345 --append-action 3456 --append-action 4567
['1234', '2345', '3456', '4567']

小贴士

  • 使用nargsaction='append'
    • nargs从用户的角度来看,它可能更直接,但是如果存在位置参数,则可能是不直观的,因为argparse无法分辨什么应该是位置参数以及什么属于nargs;如果您有位置参数,那么action='append'最终可能是一个更好的选择。
    • 如果以上是唯一真正的nargs给予'*''+''?'。如果您提供一个整数(例如4),则将选项与nargs和位置参数混合使用将不会有问题,因为argparse它将确切知道期望该选项有多少个值。
  • 不要在命令行1上使用引号
  • 不要使用type=list,因为它会返回列表列表
    • 发生这种情况的原因是,在后台argparse使用的值type来强制您选择的每个给定给定参数type,而不是所有参数的总和。
    • 您可以使用type=int(或其他任何方式)获取一个整数列表(或其他任何方式)

1:我的意思不是一般。.我的意思不是用引号将列表传递给argparse您。

TL;DR

Use the nargs option or the 'append' setting of the action option (depending on how you want the user interface to behave).

nargs

parser.add_argument('-l','--list', nargs='+', help='<Required> Set flag', required=True)
# Use like:
# python arg.py -l 1234 2345 3456 4567

nargs='+' takes 1 or more arguments, nargs='*' takes zero or more.

append

parser.add_argument('-l','--list', action='append', help='<Required> Set flag', required=True)
# Use like:
# python arg.py -l 1234 -l 2345 -l 3456 -l 4567

With append you provide the option multiple times to build up the list.

Don’t use type=list!!! – There is probably no situation where you would want to use type=list with argparse. Ever.


Let’s take a look in more detail at some of the different ways one might try to do this, and the end result.

import argparse

parser = argparse.ArgumentParser()

# By default it will fail with multiple arguments.
parser.add_argument('--default')

# Telling the type to be a list will also fail for multiple arguments,
# but give incorrect results for a single argument.
parser.add_argument('--list-type', type=list)

# This will allow you to provide multiple arguments, but you will get
# a list of lists which is not desired.
parser.add_argument('--list-type-nargs', type=list, nargs='+')

# This is the correct way to handle accepting multiple arguments.
# '+' == 1 or more.
# '*' == 0 or more.
# '?' == 0 or 1.
# An int is an explicit number of arguments to accept.
parser.add_argument('--nargs', nargs='+')

# To make the input integers
parser.add_argument('--nargs-int-type', nargs='+', type=int)

# An alternate way to accept multiple inputs, but you must
# provide the flag once per input. Of course, you can use
# type=int here if you want.
parser.add_argument('--append-action', action='append')

# To show the results of the given option to screen.
for _, value in parser.parse_args()._get_kwargs():
    if value is not None:
        print(value)

Here is the output you can expect:

$ python arg.py --default 1234 2345 3456 4567
...
arg.py: error: unrecognized arguments: 2345 3456 4567

$ python arg.py --list-type 1234 2345 3456 4567
...
arg.py: error: unrecognized arguments: 2345 3456 4567

$ # Quotes won't help here... 
$ python arg.py --list-type "1234 2345 3456 4567"
['1', '2', '3', '4', ' ', '2', '3', '4', '5', ' ', '3', '4', '5', '6', ' ', '4', '5', '6', '7']

$ python arg.py --list-type-nargs 1234 2345 3456 4567
[['1', '2', '3', '4'], ['2', '3', '4', '5'], ['3', '4', '5', '6'], ['4', '5', '6', '7']]

$ python arg.py --nargs 1234 2345 3456 4567
['1234', '2345', '3456', '4567']

$ python arg.py --nargs-int-type 1234 2345 3456 4567
[1234, 2345, 3456, 4567]

$ # Negative numbers are handled perfectly fine out of the box.
$ python arg.py --nargs-int-type -1234 2345 -3456 4567
[-1234, 2345, -3456, 4567]

$ python arg.py --append-action 1234 --append-action 2345 --append-action 3456 --append-action 4567
['1234', '2345', '3456', '4567']

Takeaways:

  • Use nargs or action='append'
    • nargs can be more straightforward from a user perspective, but it can be unintuitive if there are positional arguments because argparse can’t tell what should be a positional argument and what belongs to the nargs; if you have positional arguments then action='append' may end up being a better choice.
    • The above is only true if nargs is given '*', '+', or '?'. If you provide an integer number (such as 4) then there will be no problem mixing options with nargs and positional arguments because argparse will know exactly how many values to expect for the option.
  • Don’t use quotes on the command line1
  • Don’t use type=list, as it will return a list of lists
    • This happens because under the hood argparse uses the value of type to coerce each individual given argument you your chosen type, not the aggregate of all arguments.
    • You can use type=int (or whatever) to get a list of ints (or whatever)

1: I don’t mean in general.. I mean using quotes to pass a list to argparse is not what you want.


回答 1

我更喜欢传递一个定界字符串,稍后在脚本中对其进行解析。原因是:该列表可以是任何类型intstr,有时nargs如果有多个可选参数和位置参数,有时会遇到问题。

parser = ArgumentParser()
parser.add_argument('-l', '--list', help='delimited list input', type=str)
args = parser.parse_args()
my_list = [int(item) for item in args.list.split(',')]

然后,

python test.py -l "265340,268738,270774,270817" [other arguments]

要么,

python test.py -l 265340,268738,270774,270817 [other arguments]

会很好的工作。分隔符也可以是空格,尽管会像问题中的示例一样在参数值周围加引号。

I prefer passing a delimited string which I parse later in the script. The reasons for this are; the list can be of any type int or str, and sometimes using nargs I run into problems if there are multiple optional arguments and positional arguments.

parser = ArgumentParser()
parser.add_argument('-l', '--list', help='delimited list input', type=str)
args = parser.parse_args()
my_list = [int(item) for item in args.list.split(',')]

Then,

python test.py -l "265340,268738,270774,270817" [other arguments]

or,

python test.py -l 265340,268738,270774,270817 [other arguments]

will work fine. The delimiter can be a space, too, which would though enforce quotes around the argument value like in the example in the question.


回答 2

除之外nargschoices如果您事先知道列表,则可能要使用:

>>> parser = argparse.ArgumentParser(prog='game.py')
>>> parser.add_argument('move', choices=['rock', 'paper', 'scissors'])
>>> parser.parse_args(['rock'])
Namespace(move='rock')
>>> parser.parse_args(['fire'])
usage: game.py [-h] {rock,paper,scissors}
game.py: error: argument move: invalid choice: 'fire' (choose from 'rock',
'paper', 'scissors')

Additionally to nargs, you might want to use choices if you know the list in advance:

>>> parser = argparse.ArgumentParser(prog='game.py')
>>> parser.add_argument('move', choices=['rock', 'paper', 'scissors'])
>>> parser.parse_args(['rock'])
Namespace(move='rock')
>>> parser.parse_args(['fire'])
usage: game.py [-h] {rock,paper,scissors}
game.py: error: argument move: invalid choice: 'fire' (choose from 'rock',
'paper', 'scissors')

回答 3

在argparse的add_argument方法中使用nargs参数

我使用nargs =’ ‘作为add_argument参数。如果我没有传递任何明确的参数,我专门在选项中使用nargs =’ ‘来选择默认值

包括一个代码片段作为示例:

示例:temp_args1.py

请注意:以下示例代码是用python3编写的。通过更改打印语句的格式,可以在python2中运行

#!/usr/local/bin/python3.6

from argparse import ArgumentParser

description = 'testing for passing multiple arguments and to get list of args'
parser = ArgumentParser(description=description)
parser.add_argument('-i', '--item', action='store', dest='alist',
                    type=str, nargs='*', default=['item1', 'item2', 'item3'],
                    help="Examples: -i item1 item2, -i item3")
opts = parser.parse_args()

print("List of items: {}".format(opts.alist))

注意:我正在收集存储在列表中的多个字符串参数-opts.alist如果要获取整数列表,请将parser.add_argument上的type参数更改为int

执行结果:

python3.6 temp_agrs1.py -i item5 item6 item7
List of items: ['item5', 'item6', 'item7']

python3.6 temp_agrs1.py -i item10
List of items: ['item10']

python3.6 temp_agrs1.py
List of items: ['item1', 'item2', 'item3']

Using nargs parameter in argparse’s add_argument method

I use nargs=’‘ as an add_argument parameter. I specifically used nargs=’‘ to the option to pick defaults if I am not passing any explicit arguments

Including a code snippet as example:

Example: temp_args1.py

Please Note: The below sample code is written in python3. By changing the print statement format, can run in python2

#!/usr/local/bin/python3.6

from argparse import ArgumentParser

description = 'testing for passing multiple arguments and to get list of args'
parser = ArgumentParser(description=description)
parser.add_argument('-i', '--item', action='store', dest='alist',
                    type=str, nargs='*', default=['item1', 'item2', 'item3'],
                    help="Examples: -i item1 item2, -i item3")
opts = parser.parse_args()

print("List of items: {}".format(opts.alist))

Note: I am collecting multiple string arguments that gets stored in the list – opts.alist If you want list of integers, change the type parameter on parser.add_argument to int

Execution Result:

python3.6 temp_agrs1.py -i item5 item6 item7
List of items: ['item5', 'item6', 'item7']

python3.6 temp_agrs1.py -i item10
List of items: ['item10']

python3.6 temp_agrs1.py
List of items: ['item1', 'item2', 'item3']

回答 4

如果打算使单个开关具有多个参数,请使用nargs='+'。如果您的示例“ -l”实际上是整数:

a = argparse.ArgumentParser()
a.add_argument(
    '-l', '--list',  # either of this switches
    nargs='+',       # one or more parameters to this switch
    type=int,        # /parameters/ are ints
    dest='list',     # store in 'list'.
    default=[],      # since we're not specifying required.
)

print a.parse_args("-l 123 234 345 456".split(' '))
print a.parse_args("-l 123 -l=234 -l345 --list 456".split(' '))

产生

Namespace(list=[123, 234, 345, 456])
Namespace(list=[456])  # Attention!

如果您多次指定相同的参数,则默认操作('store')将替换现有数据。

替代方法是使用append操作:

a = argparse.ArgumentParser()
a.add_argument(
    '-l', '--list',  # either of this switches
    type=int,        # /parameters/ are ints
    dest='list',     # store in 'list'.
    default=[],      # since we're not specifying required.
    action='append', # add to the list instead of replacing it
)

print a.parse_args("-l 123 -l=234 -l345 --list 456".split(' '))

哪个产生

Namespace(list=[123, 234, 345, 456])

或者,您可以编写一个自定义处理程序/操作来解析逗号分隔的值,以便您可以

-l 123,234,345 -l 456

If you are intending to make a single switch take multiple parameters, then you use nargs='+'. If your example ‘-l’ is actually taking integers:

a = argparse.ArgumentParser()
a.add_argument(
    '-l', '--list',  # either of this switches
    nargs='+',       # one or more parameters to this switch
    type=int,        # /parameters/ are ints
    dest='list',     # store in 'list'.
    default=[],      # since we're not specifying required.
)

print a.parse_args("-l 123 234 345 456".split(' '))
print a.parse_args("-l 123 -l=234 -l345 --list 456".split(' '))

Produces

Namespace(list=[123, 234, 345, 456])
Namespace(list=[456])  # Attention!

If you specify the same argument multiple times, the default action ('store') replaces the existing data.

The alternative is to use the append action:

a = argparse.ArgumentParser()
a.add_argument(
    '-l', '--list',  # either of this switches
    type=int,        # /parameters/ are ints
    dest='list',     # store in 'list'.
    default=[],      # since we're not specifying required.
    action='append', # add to the list instead of replacing it
)

print a.parse_args("-l 123 -l=234 -l345 --list 456".split(' '))

Which produces

Namespace(list=[123, 234, 345, 456])

Or you can write a custom handler/action to parse comma-separated values so that you could do

-l 123,234,345 -l 456

回答 5

在中add_argument()type只是一个可调用对象,它接收字符串并返回选项值。

import ast

def arg_as_list(s):                                                            
    v = ast.literal_eval(s)                                                    
    if type(v) is not list:                                                    
        raise argparse.ArgumentTypeError("Argument \"%s\" is not a list" % (s))
    return v                                                                   


def foo():
    parser.add_argument("--list", type=arg_as_list, default=[],
                        help="List of values")

这将允许:

$ ./tool --list "[1,2,3,4]"

In add_argument(), type is just a callable object that receives string and returns option value.

import ast

def arg_as_list(s):                                                            
    v = ast.literal_eval(s)                                                    
    if type(v) is not list:                                                    
        raise argparse.ArgumentTypeError("Argument \"%s\" is not a list" % (s))
    return v                                                                   


def foo():
    parser.add_argument("--list", type=arg_as_list, default=[],
                        help="List of values")

This will allow to:

$ ./tool --list "[1,2,3,4]"

回答 6

如果您有一个嵌套列表,其中内部列表具有不同的类型和长度,并且您想保留该类型,例如,

[[1, 2], ["foo", "bar"], [3.14, "baz", 20]]

那么您可以使用@ sam-mason这个问题提出的解决方案,如下所示:

from argparse import ArgumentParser
import json

parser = ArgumentParser()
parser.add_argument('-l', type=json.loads)
parser.parse_args(['-l', '[[1,2],["foo","bar"],[3.14,"baz",20]]'])

这使:

Namespace(l=[[1, 2], ['foo', 'bar'], [3.14, 'baz', 20]])

If you have a nested list where the inner lists have different types and lengths and you would like to preserve the type, e.g.,

[[1, 2], ["foo", "bar"], [3.14, "baz", 20]]

then you can use the solution proposed by @sam-mason to this question, shown below:

from argparse import ArgumentParser
import json

parser = ArgumentParser()
parser.add_argument('-l', type=json.loads)
parser.parse_args(['-l', '[[1,2],["foo","bar"],[3.14,"baz",20]]'])

which gives:

Namespace(l=[[1, 2], ['foo', 'bar'], [3.14, 'baz', 20]])

回答 7

我想处理传递多个列表,整数值和字符串。

有用的链接=> 如何将Bash变量传递给Python?

def main(args):
    my_args = []
    for arg in args:
        if arg.startswith("[") and arg.endswith("]"):
            arg = arg.replace("[", "").replace("]", "")
            my_args.append(arg.split(","))
        else:
            my_args.append(arg)

    print(my_args)


if __name__ == "__main__":
    import sys
    main(sys.argv[1:])

顺序并不重要。如果要传递列表,请在之间进行操作"[""]并使用逗号分隔它们。

然后,

python test.py my_string 3 "[1,2]" "[3,4,5]"

输出=> ['my_string', '3', ['1', '2'], ['3', '4', '5']]my_args变量按顺序包含参数。

I want to handle passing multiple lists, integer values and strings.

Helpful link => How to pass a Bash variable to Python?

def main(args):
    my_args = []
    for arg in args:
        if arg.startswith("[") and arg.endswith("]"):
            arg = arg.replace("[", "").replace("]", "")
            my_args.append(arg.split(","))
        else:
            my_args.append(arg)

    print(my_args)


if __name__ == "__main__":
    import sys
    main(sys.argv[1:])

Order is not important. If you want to pass a list just do as in between "[" and "] and seperate them using a comma.

Then,

python test.py my_string 3 "[1,2]" "[3,4,5]"

Output => ['my_string', '3', ['1', '2'], ['3', '4', '5']], my_args variable contains the arguments in order.


回答 8

我认为,最优雅的解决方案是将lambda函数传递给“类型”,如Chepner所述。除此之外,如果您事先不知道列表的分隔符是什么,还可以将多个分隔符传递给re.split:

# python3 test.py -l "abc xyz, 123"

import re
import argparse

parser = argparse.ArgumentParser(description='Process a list.')
parser.add_argument('-l', '--list',
                    type=lambda s: re.split(' |, ', s),
                    required=True,
                    help='comma or space delimited list of characters')

args = parser.parse_args()
print(args.list)


# Output: ['abc', 'xyz', '123']

I think the most elegant solution is to pass a lambda function to “type”, as mentioned by Chepner. In addition to this, if you do not know beforehand what the delimiter of your list will be, you can also pass multiple delimiters to re.split:

# python3 test.py -l "abc xyz, 123"

import re
import argparse

parser = argparse.ArgumentParser(description='Process a list.')
parser.add_argument('-l', '--list',
                    type=lambda s: re.split(' |, ', s),
                    required=True,
                    help='comma or space delimited list of characters')

args = parser.parse_args()
print(args.list)


# Output: ['abc', 'xyz', '123']

Argparse可选的位置参数?

问题:Argparse可选的位置参数?

我有一个打算像这样使用的脚本: usage: installer.py dir [-h] [-v]

dir 是一个位置参数,其定义如下:

parser.add_argument('dir', default=os.getcwd())

我希望dir可以是可选的:未指定时,它应该只是cwd

不幸的是,当我不指定dir参数时,我得到了Error: Too few arguments

I have a script which is meant to be used like this: usage: installer.py dir [-h] [-v]

dir is a positional argument which is defined like this:

parser.add_argument('dir', default=os.getcwd())

I want the dir to be optional: when it’s not specified it should just be cwd.

Unfortunately when I don’t specify the dir argument, I get Error: Too few arguments.


回答 0

使用nargs='?'(或nargs='*' 如果您需要多个目录)

parser.add_argument('dir', nargs='?', default=os.getcwd())

扩展示例:

>>> import os, argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('-v', action='store_true')
_StoreTrueAction(option_strings=['-v'], dest='v', nargs=0, const=True, default=False, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('dir', nargs='?', default=os.getcwd())
_StoreAction(option_strings=[], dest='dir', nargs='?', const=None, default='/home/vinay', type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args('somedir -v'.split())
Namespace(dir='somedir', v=True)
>>> parser.parse_args('-v'.split())
Namespace(dir='/home/vinay', v=True)
>>> parser.parse_args(''.split())
Namespace(dir='/home/vinay', v=False)
>>> parser.parse_args(['somedir'])
Namespace(dir='somedir', v=False)
>>> parser.parse_args('somedir -h -v'.split())
usage: [-h] [-v] [dir]

positional arguments:
  dir

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

Use nargs='?' (or nargs='*' if you will need more than one dir)

parser.add_argument('dir', nargs='?', default=os.getcwd())

extended example:

>>> import os, argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('-v', action='store_true')
_StoreTrueAction(option_strings=['-v'], dest='v', nargs=0, const=True, default=False, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('dir', nargs='?', default=os.getcwd())
_StoreAction(option_strings=[], dest='dir', nargs='?', const=None, default='/home/vinay', type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args('somedir -v'.split())
Namespace(dir='somedir', v=True)
>>> parser.parse_args('-v'.split())
Namespace(dir='/home/vinay', v=True)
>>> parser.parse_args(''.split())
Namespace(dir='/home/vinay', v=False)
>>> parser.parse_args(['somedir'])
Namespace(dir='somedir', v=False)
>>> parser.parse_args('somedir -h -v'.split())
usage: [-h] [-v] [dir]

positional arguments:
  dir

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

回答 1

作为@VinaySajip答案的扩展。还有其他nargs值得一提的

  1. parser.add_argument('dir', nargs=1, default=os.getcwd())

N(整数)。命令行中的N个参数将一起收集到一个列表中

  1. parser.add_argument('dir', nargs='*', default=os.getcwd())

‘*’。存在的所有命令行参数都收集到一个列表中。请注意,使用多个位置参数通常没有多大意义nargs='*',但可以使用多个可选参数nargs='*'

  1. parser.add_argument('dir', nargs='+', default=os.getcwd())

‘+’。就像’*’一样,所有存在的命令行参数都被收集到一个列表中。此外,如果没有至少一个命令行参数,则会生成一条错误消息。

  1. parser.add_argument('dir', nargs=argparse.REMAINDER, default=os.getcwd())

argparse.REMAINDER。所有其余的命令行参数都收集到一个列表中。这对于分派到其他命令行实用工具的命令行实用工具通常很有用

如果nargs未提供关键字参数,则消耗的参数数量由操作确定。通常,这意味着将使用单个命令行参数,并且将生成单个项目(而不是列表)。

编辑(从@Acumenus的评论复制) nargs='?' 文档说:“?”。如果可能,将从命令行使用一个参数,并将其作为单个项目产生。如果不存在命令行参数,则将生成默认值。

As an extension to @VinaySajip answer. There are additional nargs worth mentioning.

  1. parser.add_argument('dir', nargs=1, default=os.getcwd())

N (an integer). N arguments from the command line will be gathered together into a list

  1. parser.add_argument('dir', nargs='*', default=os.getcwd())

‘*’. All command-line arguments present are gathered into a list. Note that it generally doesn’t make much sense to have more than one positional argument with nargs='*', but multiple optional arguments with nargs='*' is possible.

  1. parser.add_argument('dir', nargs='+', default=os.getcwd())

‘+’. Just like ‘*’, all command-line args present are gathered into a list. Additionally, an error message will be generated if there wasn’t at least one command-line argument present.

  1. parser.add_argument('dir', nargs=argparse.REMAINDER, default=os.getcwd())

argparse.REMAINDER. All the remaining command-line arguments are gathered into a list. This is commonly useful for command line utilities that dispatch to other command line utilities

If the nargs keyword argument is not provided, the number of arguments consumed is determined by the action. Generally this means a single command-line argument will be consumed and a single item (not a list) will be produced.

Edit (copied from a comment by @Acumenus) nargs='?' The docs say: ‘?’. One argument will be consumed from the command line if possible and produced as a single item. If no command-line argument is present, the value from default will be produced.


回答 2

parser.add_argument需要一个开关。您可以使用required=False。这是Python 2.7的样本片段:

parser = argparse.ArgumentParser(description='get dir')
parser.add_argument('--dir', type=str, help='dir', default=os.getcwd(), required=False)
args = parser.parse_args()

parser.add_argument also has a switch required. You can use required=False. Here is a sample snippet with Python 2.7:

parser = argparse.ArgumentParser(description='get dir')
parser.add_argument('--dir', type=str, help='dir', default=os.getcwd(), required=False)
args = parser.parse_args()