“argparse”,具有以破折号开头的可选位置参数

2024-06-08 20:31:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我们试图在我们使用的命令行工具上构建一个包装器脚本。我们想根据包装器脚本中的选项设置一些工具参数。我们还希望能够将本机参数直接传递给命令行工具,因为它们是在命令行上编写的。在

以下是我们得出的结论:

import argparse

parser = argparse.ArgumentParser()

parser.add_argument('positional')
parser.add_argument('-f', '--foo', action='store_true')
parser.add_argument('-b', '--bar', action='store_true')

parser.add_argument('native_arg', nargs='*')

args = parser.parse_args()
print (args)

positional是必需的。基于选项-f和{},我们将在工具调用中添加一些额外的选项。之后剩下的任何东西(如果有的话)都应该被视为本机工具参数并直接提供给工具。使用-h调用脚本会产生以下用法:

^{pr2}$

诀窍在于这些本机参数本身就是工具的选项,并且包含前导的破折号,例如-native0和{}。我们已经知道了使用双破折号来阻止argparse寻找更多选项的诀窍。以下电话:

./test.py pos -- -native0 -native1

生成预期的已分析参数:

Namespace(bar=False, foo=False, native_arg=['-native0', '-native1'], positional='pos')

不过,尝试在第一个位置参数之后添加一个选项是行不通的。更具体地说,以下呼吁:

./test.py pos --foo -- -native0 -native1

生成以下输出:

usage: [...shortened...]
test.py: error: unrecognized arguments: -- -native0 -native1

将可选参数置于位置之前:

./test.py --foo pos -- -native0 -native1

似乎有效,如下所示:

Namespace(bar=False, foo=True, native_arg=['-native0', '-native1'], positional='pos')

更奇怪的是,将native_argnargs的值更改为'+'在上述所有情况下都有效(当然,需要注意的是,至少需要一个native_arg)。在

我们是在Python代码中出错了还是这是某种argparse错误?在


Tags: 工具postestaddparser参数foo选项
2条回答

当您将非必需的位置参数与可选参数混合使用时,argparse确实很困难(有关详细信息,请参阅https://stackoverflow.com/a/47208725/1399279)。我不想提出解决这个问题的方法,而是提出一种替代方法。在

您应该检查一下^{}方法,它是为您描述的情况创建的(即将选项传递给包装好的工具)。在

In [1]: import argparse

In [2]: parser = argparse.ArgumentParser()

In [3]: parser.add_argument('positional')

In [4]: parser.add_argument('-f', ' foo', action='store_true')

In [5]: parser.add_argument('-b', ' bar', action='store_true')

In [6]: parser.parse_known_args(['pos', ' foo', '-native0', '-native1'])
Out[6]: (Namespace(bar=False, foo=True, positional='pos'), ['-native0', '-native1'])

parse_args不同,parse_known_args的输出是一个双元素元组。第一个元素是您希望从parse_args获取的Namespace实例,它包含由调用add_argument定义的所有属性。第二个元素是解析器不知道的所有参数的列表。在

我个人更喜欢这种方法,因为用户不需要记住如何调用程序的任何技巧,也不需要记住哪个选项顺序不会导致错误。在

这是一个已知问题(https://bugs.python.org/issue15112argparse:nargs='*'位置参数如果前面有一个选项和另一个位置参数,则不接受任何项目)

解析交替处理位置和选项。在处理位置时,它尝试处理输入字符串所需的任意数量。但是?或{}位置满足[],一个空字符串列表。+另一方面需要至少一个字符串

./test.py pos  foo   -native0 -native1

解析器给positional[]native-arg。然后它将“foo”赋给它的可选项。没有剩下的positionals来传递剩余的字符串,因此会引发错误。在

输入字符串的分配使用regex字符串匹配的样式化形式完成。想象一下匹配一个看起来像AA?的模式。在

为了纠正这一点,解析器必须向前看,并延迟处理native-arg。我们已经推荐了补丁,但还没有投入生产。在

@SethMMorton建议使用parse_known_args是一个很好的建议。在

早期的解析器(例如Optparse)处理所有标记的参数,但将其余的位置作为无差别列表返回。这取决于用户如何分割该列表。argparse增加了命名和解析positionals的功能,但是该算法最适合于固定的nargs,并且由于变量nargs太多而变得不稳定。在

相关问题 更多 >