argparse python模块的文档虽然很好,但我确信,对于我的初学者来说,现在太多了,我无法理解。我不需要在命令行上做数学运算,也不需要干预屏幕上的格式化行或更改选项字符。我所要做的就是"如果arg是a,那么做这个,如果b做那个,如果上面没有显示帮助并退出"。
那就查一下sys.argv你想要的论点……
试过普拉斯吗?它是一个易于使用的argparse包装器,带有大量文档。
不是你。这是AgPARSE。它试图带你去星星之旅,而不在乎你要去哪里。
又是疯狂的"Python"API:/
祝福你,马特·威尔基,因为他在任何地方都是为初学者的小脑袋而奋斗。
在Python中,最迫切需要的是一个支持argparse/getopts声明形式的库。它允许两行获取所有选项并循环文件(如果没有给出文件,则为stdin),类似于Perl的getopts('abc:d:'); while (< >) {...}。与此简单且广泛使用的构造类似的python需要多行非简单代码,这些代码必须以太多脚本的方式重复。
相关:为什么使用argparse而不是optparse?
不,文件是垃圾。大多数python文档都是。
非常糟糕,这个argparse文档
以下是我使用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的自动帮助格式,但似乎没有一个选项可以有一个未经证实的参数(更可能的是,当我看到它时我不理解它),例如,一个需要做foo.py --action install或foo.py --action remove,而不是简单的foo.py install。
@Mattwillkie然后你必须定义一个位置参数,像这样:parser.add_argument('install', help='Install the app')(注意你不能用required=True定义位置参数)
@strongma parser.parse_args()是一个名称空间,我的args局部变量是一个dict,因为vars(parser.parse_args())返回一个dict,它是完全不可重写的。
作为argparse的一个noob,这个答案真的很有帮助,因为我不知道在它们被传递之后在哪里找到选项。换言之,我需要了解argsdict是如何如上所述生成的。
'-f'和'-b'有什么意义?为什么你不能省略这个?
@用户2763361您可以省略-f和-b,这对--foo和--bar都是定义"可选"参数的有效方法(docs.python.org/2/library/argparse.html add参数me&zwnj;&8203;thod)
直接从命令行调用程序时使用"短格式",在脚本中运行程序/命令时使用"长格式"。在这种情况下,长格式的代码更容易被人阅读,因此更容易遵循代码/脚本的逻辑。
就我个人而言,我发现更容易访问参数,比如args.foo和args.bar,而不是字典语法。当然,这两种方法都可以,但args实际上不是一个字典,而是一个argparse.Namespace对象。
我对原始问题的理解是双重的。首先,对于最简单的argparse示例,我很惊讶在这里没有看到它。当然,简单地说,这也是所有的开销和小功率,但它可能会让你开始。
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("a")
args = parser.parse_args()
if args.a == 'magic.name':
print 'You nailed it!'
但是这个位置参数现在是必需的。如果您在调用这个程序时忽略了它,您将得到一个关于缺少参数的错误。这就引出了最初问题的第二部分。MattWilkie似乎想要一个没有命名标签(选项标签)的可选参数。我的建议是将上述代码修改如下:
...
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
可能会有一个更优雅的解决方案,但这是可行的,而且是极简主义的。
经过一段时间的思考,我总结出这个问题实际上最能回答被问到的问题和当时的困境。其他优秀的答案已经获得了足够多的代表来证明他们的价值,并能承受一点竞争。-)
@巴纳克:这是你想要的,无论"A"代表什么。如果需要一个参数(例如文件名),则它是在命令行中作为文件名输入的。然后,您可以自己进行处理以确定文件系统中是否存在该文件,但这是另一个问题。
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"
还请注意,添加参数时可以使用"必需"选项:
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,值。
有许多其他选项和您可以做的事情,但这应该涵盖最基本的、最常见的使用场景。
'-f'和'-b'有什么意义?为什么你不能省略这个?
对于每个运行时选项,都有一个"短格式"(一个破折号)和一个"长格式"(两个破折号)版本是相当传统的。例如,在几乎所有标准的Unix/Linux实用程序中,您都会看到这一点;使用man cp或man ls,您会发现有许多选项都有两种风格(例如-f, --force)。人们喜欢其中一种或另一种的原因可能有很大的不同,但无论如何,在程序中使用这两种形式都是相当标准的。
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
根据stackoverflow.com/questions/4480075/&hellip,nargs='?'是"可选位置"的咒语;
位置foo-bar没有转换成foo_bar的事实在bugs.python.org/issue1525中得到了解决。
我认为解决这个bug的一个更简单的方法是将参数称为"foo-bar",而不是"foo-bar",然后使用print args.foo_bar。因为它是一个位置参数,所以在调用脚本时不必指定名称,所以对用户来说并不重要。
@Luator你说得对,重新命名这个论点很容易,但是bug报告的作者提出了一个很好的例子,那就是由于不必要的认知负荷,这仍然是一个错误。使用argparse时,必须暂停并调用选项和参数的不同命名约定。请参见bugs.python.org/msg164968。
@我完全同意这是一个应该修复的错误。我只是认为重命名参数比使用getattr更容易,也更不容易混淆(它也更灵活,因为它允许您将参数从可选更改为位置,而不必更改使用值的代码)。
另一个概要介绍,受本文启发。
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时此参数的说明。
默认值:省略参数时的默认值。
类型:如果您希望使用float或int(否则为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']所述。
必需:如果需要标志,或者位置参数不是。
n args:用于捕获n个args ./myscript.py --foo a b => args.foo = ['a', 'b']
选择:限制可能的输入(指定为字符串列表,或者如果是type=int)。
以下是我在学习项目中的想法,主要归功于@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示例
请注意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)
很高兴看到文档已经更新。我向你保证,5年前OP发布这个问题时,情况并非如此。
您也可以使用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 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参数后的tuple注释具有以下含义:
说明(Argument with two possible values)
参数类型-"flag"、"option"或"positional"之一(positional)
缩写(None)
参数值类型-例如float、string(None)
限制选择集(['A', 'B'])
文档:
要了解更多关于使用plac的信息,请查看其重要文档:
Plac: Parsing the Command Line the Easy Way
加上其他人的陈述:
我通常喜欢使用"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使用getattr和setattr访问命名空间中的值。这样一来,它就不会被奇怪形成的dest值所困扰。