65

当没有给出参数时,我的脚本应该启动演示模式。我试过这个:

args = parser.parse_args()
if len(args) == 0:
    run_demo()
else:
    # evaluate args

这给出了一个*** TypeError: object of type 'Namespace' has no len()没有args列表。

我将如何实现我想要的?

4

8 回答 8

109

如果您的目标是检测何时没有为命令提供参数,那么执行此argparse操作是错误的方法(正如 Ben 很好地指出的那样)。

想的简单!:-) 我相信 argparse 不会减少人口sys.argv。因此,if not len(sys.argv) > 1,则用户没有提供任何参数。

于 2012-05-22T09:44:37.580 回答
20

argparse 允许您根据您的规范和正在解析的命令行设置(在命名空间对象内)您添加到解析器的参数中提到的所有变量。如果您设置了默认值,那么如果在命令行上没有看到这些变量,那么它们将具有该默认值,命名空间对象中也不会缺少它们。如果您指定默认值,则存在隐式默认值None. 所以检查 Namespace 对象的长度,不管你怎么做,作为检查是否有任何参数被解析的方法是没有意义的;它应该始终具有相同的长度。

相反,如果你知道你有一堆没有默认值的参数,并且你想检查它们中的任何一个是否被设置为任何非None值......就这样做。您可以使用列表推导和vars函数来遍历它们,而不必从add_argument调用中复制名称列表,如 Martijn 的回答所示。

如果您的某些参数具有默认值,那么它会变得有点棘手,如果它们具有可以在命令行上显式提供的默认值(例如,默认为 0 的数字参数使得无法告诉用户默认值)提供 0)。在那种情况下,我不确定是否有一个通用的解决方案在不知道参数是什么的情况下总是有效的。

于 2012-05-22T09:30:56.177 回答
11

如果真的需要参数编号(无论出于何种原因)。我发现这段代码很有帮助(但不知道它优化了多少,我会很感激任何评论)。

args = parser.parse_args()
print( len( vars(args) ) )

此版本仅计算 -xx 参数,而不计算传递的任何附加值。

如果一个人想要所有东西(还有传递的值),那么就像len(sys.argv)前面提到的那样使用。

于 2013-08-21T15:25:13.760 回答
10

不要使用 argparse。相反,只需使用sys.argv. argparse创建一个命名空间,因此它总是会为您提供一个带有它们的值的“dict”,具体取决于您在调用脚本时使用的参数。

这是我过去所做的:

args = parser.parse_args()
if len(sys.argv) == 1:
    parser.print_help()
    sys.exit()
return args
于 2018-01-04T23:22:47.370 回答
7

我知道这是一个旧线程,但我找到了一个更直接的解决方案,可能对其他人也有用:

您可以检查是否已传递任何参数:

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()它来把它变成 adict以便我们可以访问这些值。

最后,由于我们现在dict手头有 a ,我们可以获取所有值(在 a 中list), with .values(),并使用内置any()函数检查是否有任何值不是None。为了更清楚:如果在您提供给它的列表中没有一个 is not 或(检查文档以供参考)的单个值,则返回any()FalseNoneFalse0

希望能帮助到你。

于 2019-07-22T19:07:42.800 回答
3

让我们假设以下示例来扩展您的完整性:

#!/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.inputargs.length或访问它args.verbose。您可以通过执行来验证这一点,print(args)这实际上会显示如下内容:

Namespace(input=None, length=None, verbose=False)

因为 verbose 设置为True, 如果存在,并且 input 和 length 只是变量,不必实例化(不提供参数)。

group = parser.add_mutually_exclusive_group()如果您想确保不能同时提供两个属性,这也很有帮助。

如需进一步参考,请参阅:

于 2017-03-28T22:00:58.033 回答
1

我扩展了 2dvisio 的概念来计算非零或无参数:

vm_opts = parser.parse_args()
v = vars(vm_opts)
n_args = sum([ 1 for a in v.values( ) if a])
于 2016-11-16T16:42:55.993 回答
0

对于要检查是否已传递所有输入中相同的单一类型参数的最简单情况,您可以使用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")

长度用作代理来检查是否传递了任何参数。如果您想知道哪个已通过,您可以解压缩密钥并检查更改的索引。

np.array()接受更复杂情况的逻辑运算符。

于 2021-01-22T18:00:37.513 回答