Python argparse命令行标记不带参数

506

如何在命令行参数中添加可选标志?

例如,我可以这样写:

python myprog.py 
或者
python myprog.py -w

我尝试过

parser.add_argument('-w')

但我只是收到一个错误信息,内容是

Usage [-w W]
error: argument -w: expected one argument

我理解这意味着它需要一个-w选项的参数值。有什么方法只接受一个标志?

我发现http://docs.python.org/library/argparse.html对于这个问题不太清晰。


4
如果你只是想要在脚本中使用一个标志,那么sys.argv会更容易一些。除非你特别想学习argparse,因为它是一个很方便的模块需要了解。 - chown
17
即使现在我知道答案,我仍然不明白我如何从文档中理解它。 - Andreas Haferburg
5个回答

826
按照您的代码,命令行参数-w后需要提供一个值作为参数w。如果您只是想通过将变量设置为TrueFalse来切换开关,请看一下这里(具体来说是store_true和store_false)。
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-w', action='store_true')

action='store_true' 表示默认值为 False

反之,action='store_false' 则表示默认值为 True


5
@Jdog,你有任何想法为什么这对我不起作用吗?w 总是 False - Iulian Onofrei
对我来说,无论何时都是True。 - kafka

80

添加一个快速片段以准备执行:

源代码:myparser.py

import argparse
parser = argparse.ArgumentParser(description="Flip a switch by setting a flag")
parser.add_argument('-w', action='store_true')

args = parser.parse_args()
print args.w

用法:

python myparser.py -w
>> True

13

你的脚本是正确的。但默认情况下它是无类型的。所以只要任何值赋给args.argument_name变量,除了None之外,它都被视为真。

我建议你添加action="store_true"。这将使标志的True/False类型。如果使用了它,则为True,否则为False。

import argparse
parser = argparse.ArgumentParser('parser-name')
parser.add_argument("-f","--flag",action="store_true",help="just a flag argument")

用法

$ python3 script.py -f

在解析后,当通过 args.f 进行检查时返回 true。

args = parser.parse_args()
print(args.f)
>>>true

3
如果您正在寻找二进制标志,则argparse actions store_truestore_false正好提供此功能。这种方法在@Jdog的答案中得到了很好的解释。 官方文档也相当清晰。我只需要用一行代码来完善示例,以便非常清楚地说明store_true/store_false的作用:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', action='store_true')
>>> parser.add_argument('--fov', action='store_true')  # this is not in the docs!
>>> parser.add_argument('--bar', action='store_false')
>>> parser.add_argument('--baz', action='store_false')
>>> parser.parse_args('--foo --bar'.split())  # --baz and --fov are missing
Out[4]: Namespace(bar=False, baz=True, foo=True, fov=False)  # mind the fov=False

一个稍微更强大的方法是使用count动作。通常在运行命令时已经使用了这种类型的标记来设置详细程度。

例如,ssh 的详细模式标志 -v 是一个计数器:

-v 详细模式。使 ssh 打印有关其进度的调试消息。这对于调试连接、验证和配置问题非常有帮助。多个 -v 选项会增加详细程度。最大值为3。

因此,如果您运行ssh,它是无详细信息的,ssh -v稍微详细一些,ssh -vvv则是最大详细程度。

在 Python 中,可以使用 argparse 定义这样一个计数器标志,如下所示:

parser.add_argument('--verbose', '-v', action='count', default=0)

如果您想将其用作布尔值(True/False)标志,则需要将args.verbose转换为布尔值。您可以自己明确地执行此操作,也可以依赖条件语句,例如if args.verbose: ...
这里是一个完整的工作示例,以说明如何使用计数器标志:
使用脚本test.py:
#!/usr/bin/env python3
# test.py
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--verbose', '-v', action='count', default=0)
args = parser.parse_args()

if args.verbose:
    print('verbose')
    print(f'verbosity level: {args.verbose}')
else:
    print('non-verbose')

你会得到以下输出:

python test.py 
>> non-verbose 

python test.py -v
>> verbose
>> verbosity level: 1

python test.py -vvv
>> verbose
>> verbosity level: 3

1
这满足了我需要将参数传递而不赋予任何值的需求,感谢您发布这个。 - that_roy

-13
以下是一种快速方法,仅需要sys就可以完成,但功能有限: flag = "--flag" in sys.argv[1:] [1:] 是为了防止文件名为 --flag 的情况。

18
我登录只是为了表达这个主意从长远来看是多么糟糕的想法。想象一下,你从检查字符串“--flag”是否在sys.argv中开始。然后你查看sys.argv[-1]的结尾,以确定要打开哪个文件。突然间,如果你试图打开一个名为“--flag”的文件,那么它将会出现意外行为,更糟糕的是,当不受信任的数据最终传递给argv时,这通常会成为安全漏洞。最终,这种方法不应该被采用。真正的参数解析器要更加健壮... - timthelion
6
如上所述,这个解决方案根本不够健壮,但如果你需要非常快地完成这项任务(例如进行测试),它还是可以使用的。一定要远离生产代码。 - Jonathan Sudiaman
像这样的不好的例子在某种程度上也是好的。它们向你展示了什么是不应该做的。有时候你生命中的职责就是作为他人的警告而存在。 - Anjan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接