如何创建具有多个位置参数的 argparse 互斥组?
How can I create an argparse mutually exclusive group with multiple positional parameters?
我正在尝试解析命令行参数,使得以下三种可能性成为可能:
script
script file1 file2 file3 …
script -p pattern
因此,文件列表是可选的。如果指定了 -p pattern
选项,则命令行上不能有任何其他内容。以 "usage" 格式表示,它可能看起来像这样:
script [-p pattern | file [file …]]
我认为使用 Python 的 argparse
模块的方法是这样的:
parser = argparse.ArgumentParser(prog=base)
group = parser.add_mutually_exclusive_group()
group.add_argument('-p', '--pattern', help="Operate on files that match the glob pattern")
group.add_argument('files', nargs="*", help="files to operate on")
args = parser.parse_args()
但是Python抱怨我的位置参数需要是可选的:
Traceback (most recent call last):
File "script", line 92, in <module>
group.add_argument('files', nargs="*", help="files to operate on")
…
ValueError: mutually exclusive arguments must be optional
但是 argparse documentation 说 "*"
参数 nargs
意味着它是可选的。
我也找不到 nargs
的任何其他值来解决问题。我最接近的是使用 nargs="?"
,但它只抓取一个文件,而不是任何数字的可选列表。
是否可以使用 argparse
来组成这种参数语法?
简答
将 default
添加到 *
位置
长
引发错误的代码是,
if action.required:
msg = _('mutually exclusive arguments must be optional')
raise ValueError(msg)
如果我向解析器添加 *,我会看到设置了 required
属性:
In [396]: a=p.add_argument('bar',nargs='*')
In [397]: a
Out[397]: _StoreAction(option_strings=[], dest='bar', nargs='*', const=None, default=None, type=None, choices=None, help=None, metavar=None)
In [398]: a.required
Out[398]: True
而 ?
则为 False。我将在代码中进一步挖掘以了解差异的原因。它可能是一个错误或被忽视 'feature',或者可能有一个很好的理由。 'optional' positionals 的一个棘手的事情是 no-answer 是一个答案,也就是说,一个空的值列表是有效的。
In [399]: args=p.parse_args([])
In [400]: args
Out[400]: Namespace(bar=[], ....)
所以 mutually_exclusive 必须有一些方法来区分默认的 []
和真实的 []
。
现在我建议使用 --files
,如果您希望 argparse
执行互斥测试,则使用标记参数而不是位置参数。
设置位置 required
属性的代码是:
# mark positional arguments as required if at least one is
# always required
if kwargs.get('nargs') not in [OPTIONAL, ZERO_OR_MORE]:
kwargs['required'] = True
if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs:
kwargs['required'] = True
所以解决方案是为 *
指定默认值
In [401]: p=argparse.ArgumentParser()
In [402]: g=p.add_mutually_exclusive_group()
In [403]: g.add_argument('--foo')
Out[403]: _StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
In [404]: g.add_argument('files',nargs='*',default=None)
Out[404]: _StoreAction(option_strings=[], dest='files', nargs='*', const=None, default=None, type=None, choices=None, help=None, metavar=None)
In [405]: p.parse_args([])
Out[405]: Namespace(files=[], foo=None)
默认值甚至可以是 []
。如果给出 none,解析器能够区分您提供的默认值和它使用的默认值。
哎呀 - default=None
错了。它通过了 add_argument
和 required
测试,但产生了 mutually_exclusive 错误。细节在于代码如何区分用户定义的默认值和自动的默认值。所以使用 None
.
以外的任何东西
我在文档中没有看到任何关于此的信息。我必须检查 bug/issues 才能看到该主题已被讨论。它可能也出现在 SO 之前。
您正在尝试使用 'files' 参数来捕获多个文件,但您没有在 cmdline 示例中提供它。我认为图书馆会因为您没有使用破折号前缀而感到困惑。我建议如下:
import argparse
parser = argparse.ArgumentParser(prog="base")
group = parser.add_mutually_exclusive_group()
group.add_argument('-p', '--pattern', action="store", help="Operate on files that match the glob pattern")
group.add_argument('-f', '--files', nargs="*", action="store", help="files to operate on")
args = parser.parse_args()
print args.pattern
print args.files
import argparse
parse = argparse.ArgumentParser()
parse.add_argument("-p",'--pattern',help="Operates on File")
parse.add_argument("files",nargs = "*",help="Files to operate on")
arglist = parse.parse_args(["-p","pattern"])
print arglist
arglist = parse.parse_args()
print arglist
arglist = parse.parse_args(["file1","file2","file3"])
print arglist
我正在尝试解析命令行参数,使得以下三种可能性成为可能:
script
script file1 file2 file3 …
script -p pattern
因此,文件列表是可选的。如果指定了 -p pattern
选项,则命令行上不能有任何其他内容。以 "usage" 格式表示,它可能看起来像这样:
script [-p pattern | file [file …]]
我认为使用 Python 的 argparse
模块的方法是这样的:
parser = argparse.ArgumentParser(prog=base)
group = parser.add_mutually_exclusive_group()
group.add_argument('-p', '--pattern', help="Operate on files that match the glob pattern")
group.add_argument('files', nargs="*", help="files to operate on")
args = parser.parse_args()
但是Python抱怨我的位置参数需要是可选的:
Traceback (most recent call last):
File "script", line 92, in <module>
group.add_argument('files', nargs="*", help="files to operate on")
…
ValueError: mutually exclusive arguments must be optional
但是 argparse documentation 说 "*"
参数 nargs
意味着它是可选的。
我也找不到 nargs
的任何其他值来解决问题。我最接近的是使用 nargs="?"
,但它只抓取一个文件,而不是任何数字的可选列表。
是否可以使用 argparse
来组成这种参数语法?
简答
将 default
添加到 *
位置
长
引发错误的代码是,
if action.required:
msg = _('mutually exclusive arguments must be optional')
raise ValueError(msg)
如果我向解析器添加 *,我会看到设置了 required
属性:
In [396]: a=p.add_argument('bar',nargs='*')
In [397]: a
Out[397]: _StoreAction(option_strings=[], dest='bar', nargs='*', const=None, default=None, type=None, choices=None, help=None, metavar=None)
In [398]: a.required
Out[398]: True
而 ?
则为 False。我将在代码中进一步挖掘以了解差异的原因。它可能是一个错误或被忽视 'feature',或者可能有一个很好的理由。 'optional' positionals 的一个棘手的事情是 no-answer 是一个答案,也就是说,一个空的值列表是有效的。
In [399]: args=p.parse_args([])
In [400]: args
Out[400]: Namespace(bar=[], ....)
所以 mutually_exclusive 必须有一些方法来区分默认的 []
和真实的 []
。
现在我建议使用 --files
,如果您希望 argparse
执行互斥测试,则使用标记参数而不是位置参数。
设置位置 required
属性的代码是:
# mark positional arguments as required if at least one is
# always required
if kwargs.get('nargs') not in [OPTIONAL, ZERO_OR_MORE]:
kwargs['required'] = True
if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs:
kwargs['required'] = True
所以解决方案是为 *
In [401]: p=argparse.ArgumentParser()
In [402]: g=p.add_mutually_exclusive_group()
In [403]: g.add_argument('--foo')
Out[403]: _StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
In [404]: g.add_argument('files',nargs='*',default=None)
Out[404]: _StoreAction(option_strings=[], dest='files', nargs='*', const=None, default=None, type=None, choices=None, help=None, metavar=None)
In [405]: p.parse_args([])
Out[405]: Namespace(files=[], foo=None)
默认值甚至可以是 []
。如果给出 none,解析器能够区分您提供的默认值和它使用的默认值。
哎呀 - default=None
错了。它通过了 add_argument
和 required
测试,但产生了 mutually_exclusive 错误。细节在于代码如何区分用户定义的默认值和自动的默认值。所以使用 None
.
我在文档中没有看到任何关于此的信息。我必须检查 bug/issues 才能看到该主题已被讨论。它可能也出现在 SO 之前。
您正在尝试使用 'files' 参数来捕获多个文件,但您没有在 cmdline 示例中提供它。我认为图书馆会因为您没有使用破折号前缀而感到困惑。我建议如下:
import argparse
parser = argparse.ArgumentParser(prog="base")
group = parser.add_mutually_exclusive_group()
group.add_argument('-p', '--pattern', action="store", help="Operate on files that match the glob pattern")
group.add_argument('-f', '--files', nargs="*", action="store", help="files to operate on")
args = parser.parse_args()
print args.pattern
print args.files
import argparse
parse = argparse.ArgumentParser()
parse.add_argument("-p",'--pattern',help="Operates on File")
parse.add_argument("files",nargs = "*",help="Files to operate on")
arglist = parse.parse_args(["-p","pattern"])
print arglist
arglist = parse.parse_args()
print arglist
arglist = parse.parse_args(["file1","file2","file3"])
print arglist