Argparse:检查是不是传递了任何参数
Posted
技术标签:
【中文标题】Argparse:检查是不是传递了任何参数【英文标题】:Argparse: Check if any arguments have been passedArgparse:检查是否传递了任何参数 【发布时间】:2012-05-28 17:36:35 【问题描述】:当没有给出参数时,我的脚本应该启动演示模式。我试过这个:
args = parser.parse_args()
if len(args) == 0:
run_demo()
else:
# evaluate args
这给出了*** TypeError: object of type 'Namespace' has no len()
,因为args
没有列表。
我将如何实现我想要的?
【问题讨论】:
使用try except来捕获TypeError,这样就知道什么都没有通过 @avasal,len(args)
总是抛出 TypeError。
【参考方案1】:
如果您的目标是检测何时没有为命令提供参数,那么通过argparse
执行此操作是错误的方法(正如 Ben 很好地指出的那样)。
想得简单! :-) 我相信 argparse 不会减少 sys.argv
。所以,if not len(sys.argv) > 1
,那么用户没有提供任何参数。
【讨论】:
它有效,它可能是更好/最简单的方法:D 接受了这个答案,因为它解决了我的问题,我不必重新考虑。 => 坏我 ;) +1 针对手头问题的实用建议比我针对None
检查所有选项的建议要实用得多。
请注意,这不适用于检查提供给任意嵌套子解析器的参数数量。【参考方案2】:
argparse 允许您根据您的规范和正在解析的命令行设置(在命名空间对象内)您添加到解析器的参数中提到的所有变量。如果您设置了默认值,那么如果在命令行上没有看到这些变量,那么它们将具有该默认值,命名空间对象中也不会缺少它们。如果您不指定默认值,则有一个隐式默认值None
。所以检查 Namespace 对象的长度,不管你怎么做,作为检查是否有任何参数被解析的方法是没有意义的;它应该始终具有相同的长度。
相反,如果你知道你有一堆没有默认值的参数,并且你想检查它们中的任何一个是否被设置为任何非None
值......就这样做。您可以使用列表解析和 vars
函数来循环它们,而不必复制 add_argument
调用中的名称列表,如 Martijn 的回答所示。
如果你的一些参数有默认值,那就有点棘手了来自提供 0 的用户)。在那种情况下,我不确定是否有一个通用的解决方案在不知道参数是什么的情况下始终有效。
【讨论】:
【参考方案3】:如果真的需要参数编号(无论出于何种原因)。 我发现这段代码很有帮助(但不知道它优化了多少,如果有任何评论,我将不胜感激)。
args = parser.parse_args()
print( len( vars(args) ) )
此版本仅计算 -xx 参数,不计算传递的任何附加值。
如果一个人想要所有东西(也包括传递的值),那么只需使用前面提到的len(sys.argv)
。
【讨论】:
【参考方案4】:不要使用 argparse。相反,只需使用sys.argv
。 argparse
创建了一个命名空间,因此它始终会为您提供一个包含其值的“dict”,具体取决于您在调用脚本时使用的参数。
这是我过去所做的:
args = parser.parse_args()
if len(sys.argv) == 1:
parser.print_help()
sys.exit()
return args
【讨论】:
【参考方案5】:我知道这是一个旧线程,但我找到了一个更直接的解决方案,可能对其他人也有用:
您可以检查是否已传递任何参数:
if any(vars(args).values()):
# evaluate args
或者,如果没有传递任何参数(注意not
运算符):
if not any(vars(args).values()):
run_demo()
说明:
parse_args()
返回一个包含每个参数名称及其关联值的“命名空间”对象。
示例:Namespace(arg1='myfile.txt', arg2='some/path/to/some/folder')
如果没有传递参数,parse_args()
将返回相同的对象,但所有值都为None
。
示例:Namespace(arg1=None, arg2=None)
不过,此对象不可迭代,因此您必须使用 vars()
将其转换为 dict
,以便我们可以访问这些值。
最后,由于我们现在手头有一个dict
,我们可以使用.values()
获取所有值(在list
中),并使用内置的any()
函数来检查是否有任何值值不是None
。
为了更清楚:any()
返回 False
如果在您提供给它的列表中没有一个值不是 None
、False
或 0
(查看文档以供参考) .
希望对你有帮助。
【讨论】:
如果你有默认参数,这将不起作用,因为它们会覆盖None
。【参考方案6】:
让我们假设以下示例来扩展您的完整性:
#!/usr/bin/env python3
import argparse
...
def main():
parser = argparse.ArgumentParser()
parser.add_argument('input', nargs='?' action='store')
parser.add_argument('-l', '--length', type=int, action='store')
parser.add_argument('-v', '--verbose', action='store_true')
args = parser.parse_args()
if (args.input == None and args.length == None):
parser.print_help()
else:
print(args)
if __name__ == '__main__':
main()
@Ben 提到的您的命名空间对象在此示例中是 args
。从parser.add_argument
中的字符串创建一个变量。您可以通过args.input
或args.length
或args.verbose
访问它。您可以通过执行 print(args)
来验证这一点,这实际上会显示如下内容:
Namespace(input=None, length=None, verbose=False)
因为详细设置为True
,如果存在,输入和长度只是变量,不必实例化(不提供参数)。
如果你想确保不能同时提供两个属性,group = parser.add_mutually_exclusive_group()
也有帮助。
更多参考,请参考:
https://docs.python.org/3/howto/argparse.html 结构良好的 HOWTO https://docs.python.org/3/library/argparse.html argparse 模块文档【讨论】:
创意?。喜欢这个答案!【参考方案7】:我将 2dvisio 的概念扩展为计算非零或无参数:
vm_opts = parser.parse_args()
v = vars(vm_opts)
n_args = sum([ 1 for a in v.values( ) if a])
【讨论】:
如果使用 unittest 来测试带有 argparse 的东西,这很有用,在这种情况下,接受的答案可能会出现错误。【参考方案8】:对于最简单的情况,您想要检查是否已传递所有输入中相同的单一类型的参数,您可以使用argparse
和numpy
分三步完成。
import argparse
import numpy as np
args = parser.parse_args()
# namespace to dictionary
args_dict = vars(args)
# unpack values from dictionary, pass to array
values = np.array([*args_dict.values()])
# Check if the defaults have changed
args_indices = np.where(values != default)[0]
# Did we pass any arguments?
if len(values) == len(args_indices):
print("No arguments were passed")
长度用作代理来检查是否已传递 any 或 no 参数。如果你想知道哪个被通过了,你可以打开密钥并检查更改的索引。
np.array()
接受更复杂情况的逻辑运算符。
【讨论】:
你可以使用defaults = vars(parser.parse_args([]))
得到一个带有所有默认值的Namespace
你是对的,谢谢。您可以从您的代码 sn-p 中选择一个默认值 :)以上是关于Argparse:检查是不是传递了任何参数的主要内容,如果未能解决你的问题,请参考以下文章
如何在同一个 python 脚本中使用 sys 和 argparse 而不会出现无法识别的参数错误?