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


529

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


15
然后只要检查sys.argv您想要的论点即可...
JBernardo 2011年

10
曾经尝试过普拉克吗?使用出色的文档,可以很容易地在argparse上使用包装器。
kirbyfan64sos 2013年

157
不是你 它是argparse。它试图带您去繁星点点的旅程,并且不在乎您的去向。
Florian Heigl 2014年

11
再次疯狂的“ pythonic” API:/
mlvljr

68
祝福您Matt Wilkie,因为他可以站到处都是微小的初学者。
polka

Answers:


255

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

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


4
经过一段时间的思考,我得出结论,这个问题实际上可以最好地回答所问的问题和我当时所处的困境。其他出色的答案赢得了足够多的代表,足以证明自己的价值,并且可以承受一点竞争。:-)
马特·威尔基2014年

@badnack:无论您想要什么,无论'a'代表什么。如果需要一个参数(例如文件名),则它是在命令行中作为文件名输入的。然后,您可以进行自己的处理以确定文件系统中是否存在该文件,但这是另一项问答。
mightypile

363

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

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


3
如我对另一个答案的评论中所述,我想保留argparse的自动帮助格式,但似乎没有选择保留不加修饰的参数(很可能我看到它时只是不理解它) ),例如,一个需要做的foo.py --action installfoo.py --action remove而不是简单的foo.py install
马特·威尔基

7
@mattwilkie然后,您必须像这样定义一个位置参数:( parser.add_argument('install', help='Install the app') 注意,您不能使用来定义位置参数required=True
Diego Navarro

32
作为argparse的菜鸟,这个答案确实很有帮助,因为我不知道这些选项通过后在哪里可以找到。换句话说,我需要了解args字典是如何生成的。
mrKelley

3
直接从命令行调用程序时,请使用“短格式”;在脚本中运行程序/命令时,请使用“长格式”。在这种情况下,长格式更易于阅读,因此更容易遵循代码/脚本的逻辑。
奥拉2014年

17
我个人认为访问参数更干净 args.fooargs.bar而不是字典语法。两种方法当然都可以,但是args实际上不是字典而是argparse.Namespace对象。
Michael Mior 2014年

210

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值。

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


3
什么是的点'-f''-b'?你为什么不能忽略这个?
user2763361 2014年

13
每个运行时选项同时具有“短格式”(一个破折号)和“长格式”(两个破折号)版本是很常规的。例如,几乎在每个标准的Unix / Linux实用程序中,您都会看到它。做一个man cpor man ls,您会发现两种选择都有很多选择(例如-f, --force)。人们偏爱其中一种的原因可能多种多样,但是无论如何,这两种形式都可以在您的程序中使用是相当标准的。
DMH 2014年

59

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


bugs.python.org/issue15125中解决了位置foo-bar未转换为foo_bar事实
hpaulj 2013年

2
我认为此错误的更简单解决方法是只调用参数“ foo_bar”而不是“ foo-bar”,然后开始print args.foo_bar工作。由于它是一个位置参数,因此您在调用脚本时不必指定名称,因此对用户而言无关紧要。
luator

@luator是的,很容易重命名该参数,但是错误报告的作者很好地证明了这仍然是一个不合适的功能,因为不必要的认知负担。使用argparse时,必须暂停并重新调用选项和参数的不同命名约定。参见bugs.python.org/msg164968
Mark E. Haase 2015年

1
@mehaase我完全同意这是应该解决的错误功能。我只是认为重命名该参数比必须使用的方法更轻松,更容易混淆getattr(它还更加灵活,因为它允许您将参数从可选更改为位置,而不必更改使用该值的代码)。
luator

22

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

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

12

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

很高兴看到文档已更新。我向您保证,五年前OP发布问题时并非如此。
ntwrkguru

10

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


2
最后一个有意义的例子
opentokix

5

您也可以使用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:轻松解析命令行


4

除了其他人所说的:

我通常喜欢使用'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使用getattrsetattr访问命名空间中的值。这样,它就不会被奇怪的dest值所困扰。
hpaulj

1

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

-1

最简单的答案!

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

此答案不会添加任何新内容/与现有答案不同。
NVS Abhilash

我最清楚,谈话很便宜,请显示代码
gouxute
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.