接受固定数量的参数,或使用固定数量的默认值不接受参数

如何解决接受固定数量的参数,或使用固定数量的默认值不接受参数

我想允许 2 个参数或 0 个参数并回退到认值。我认为应该这样做

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('myargs',nargs=2,default=['foo','bar'])

然而,这会抛出 2 个参数以外的任何东西(因此从不调用认值):

print(parser.parse_args(['a','b'])) # 2 arguments accepted
print(parser.parse_args([])) # throws

我的问题是,(如何)无需额外代码即可完成此操作。 IE。我想找到比例如这个解决方法更优雅和更认的 argparse

import argparse

def parse(args):

    parser = argparse.ArgumentParser()
    parser.add_argument('myargs',nargs='*','bar'])
    a = parser.parse_args(args)

    if len(a.myargs) != 2:
        raise IOError('Incorrect number of arguments')

    return a

print(parse([])) # defaults
print(parse(['a','b'])) # 2 arguments accepted
print(parse(['a','b','c'])) # throws (as excepted)

解决方法

argparse 中,没有前缀的参数(默认前缀是 - 表示缩写或 -- 表示完整参数名称)被认为是强制性的。所以,如果你想有一个可选的参数,你可以这样做:

parser = argparse.ArgumentParser()
parser.add_argument('--myargs',nargs=2,default=['foo','bar'])

在这种情况下,如果你不传递任何参数,它会像预期的那样工作:

print(parser.parse_args([]))

Namespace(myargs=['foo','bar'])

另一方面,如果您提供相同的值:

print(parser.parse_args(['--myargs','a','b']))

Namespace(myargs=['a','b'])

如果您在 myargs 之后传递了错误数量的参数,则会引发错误:

print(parser.parse_args(['--myargs','a']))

usage: scratch_2.py [-h] [--myargs MYARGS MYARGS]
<your script name>: error: argument --myargs: expected 2 arguments

另一种(更长的)方法是定义一个自定义操作来解析参数:

class CustomParsePositional(argparse.Action):
    """Action to parse arguments with a custom processing"""
    def __init__(self,option_strings,dest,nargs=None,**kwargs):
        super().__init__(option_strings,nargs='*',**kwargs)
        self._custom_nargs = len(kwargs.get('default',[]))
    def __call__(self,parser,namespace,values,option_string=None):
        if len(values) != self._custom_nargs:
            parser.error('Incorrect number of arguments')
        namespace.__setattr__(self.dest,values)

parser = argparse.ArgumentParser()
parser.add_argument('myargs','bar'],type=str,action=CustomParsePositional)

在这种情况下,预期值的数量由 defaultadd_argument 参数中的项目数推断。这里有一些例子:

print(parser.parse_args(['a','b']))
print(parser.parse_args([]))
print(parser.parse_args(['a']))


Namespace(myargs=['a','b'])
Namespace(myargs=['foo','bar'])
usage: scratch_2.py [-h] [myargs [myargs ...]]
<your script name>: error: Incorrect number of arguments

如果你传递 3 个值,你也会得到一个错误:

print(parser.parse_args(['a','b','c']))

usage: scratch_2.py [-h] [myargs [myargs ...]]
<your script name>: error: Incorrect number of arguments
,

argparse 解析工作原理的简要说明可能会有所帮助。

值收集在 namespace 对象中。在解析开始时,default 值都放在 namespace 中。然后,当在用户输入中遇到参数时,它们会按照 add_argument 中的指定进行解析,并将值放置在 namespace 中,覆盖默认值。

标记参数在看到标志时被解析,例如'--foo bar',但需要像您这样的位置,并采用 nargs 指定的确切字符串数。在这种情况下,它将使用 2 个字符串。所以对于这个定义,default 参数是没有用的。

使用 nargs='*',任意数量的字符串都可以满足它。 0 字符串的情况得到特殊处理,并将默认值放在 namespace 中。

在解析后添加检查并没有什么不雅的地方。错误信息可以简化为:

if len(a.myargs) != 2:
    parser.error('Incorrect number of arguments')

旧的解析器,如 optparse 处理所有标记的参数,并返回 extras 中的其余部分供您处理。 argparse 处理那些 extras。使用固定的 nargs 处理位置是最简单的。一个带有变量 nargs 的位置通常可以正常工作,但很难使用多个。如果你用 * 指定了两个动作,解析器应该如何分配字符串?

是的,您可以定义自定义 Action 类来处理特殊情况,但结果通常不如简单的解析后检查那么优雅 (IMO)。我不给聪明加分:)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?