我们试图在我们使用的命令行工具上构建一个包装器脚本。我们想根据包装器脚本中的选项设置一些工具参数。我们还希望能够将本机参数直接传递给命令行工具,因为它们是在命令行上编写的。在
以下是我们得出的结论:
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
调用脚本会产生以下用法:
诀窍在于这些本机参数本身就是工具的选项,并且包含前导的破折号,例如-native0
和{
./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_arg
的nargs
的值更改为'+'
在上述所有情况下都有效(当然,需要注意的是,至少需要一个native_arg
)。在
我们是在Python代码中出错了还是这是某种argparse错误?在
当您将非必需的位置参数与可选参数混合使用时,
argparse
确实很困难(有关详细信息,请参阅https://stackoverflow.com/a/47208725/1399279)。我不想提出解决这个问题的方法,而是提出一种替代方法。在您应该检查一下^{} 方法,它是为您描述的情况创建的(即将选项传递给包装好的工具)。在
与
parse_args
不同,parse_known_args
的输出是一个双元素元组。第一个元素是您希望从parse_args
获取的Namespace
实例,它包含由调用add_argument
定义的所有属性。第二个元素是解析器不知道的所有参数的列表。在我个人更喜欢这种方法,因为用户不需要记住如何调用程序的任何技巧,也不需要记住哪个选项顺序不会导致错误。在
这是一个已知问题(https://bugs.python.org/issue15112,argparse:nargs='*'位置参数如果前面有一个选项和另一个位置参数,则不接受任何项目)
解析交替处理位置和选项。在处理位置时,它尝试处理输入字符串所需的任意数量。但是}位置满足
?
或{[]
,一个空字符串列表。+
另一方面需要至少一个字符串解析器给
positional
,[]
给native-arg
。然后它将“foo”赋给它的可选项。没有剩下的positionals
来传递剩余的字符串,因此会引发错误。在输入字符串的分配使用
regex
字符串匹配的样式化形式完成。想象一下匹配一个看起来像AA?
的模式。在为了纠正这一点,解析器必须向前看,并延迟处理
native-arg
。我们已经推荐了补丁,但还没有投入生产。在@SethMMorton建议使用
parse_known_args
是一个很好的建议。在早期的解析器(例如Optparse)处理所有标记的参数,但将其余的位置作为无差别列表返回。这取决于用户如何分割该列表。
argparse
增加了命名和解析positionals
的功能,但是该算法最适合于固定的nargs
,并且由于变量nargs
太多而变得不稳定。在相关问题 更多 >
编程相关推荐