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

Tud*_*imi 6 python argparse

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

这是我们想出的:

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)
Run Code Online (Sandbox Code Playgroud)

positional是强制性的。基于这些选项-f-b我们会向我们的工具调用添加一些额外的选项。之后留下的任何东西(如果有的话)都应该被视为本机工具参数并直接提供给工具。调用我们的脚本-h产生以下用法:

usage: test.py [-h] [-f] [-b] positional [native_arg [native_arg ...]]
Run Code Online (Sandbox Code Playgroud)

诀窍是这些本机参数本身就是该工具的选项,并包含前导破折号,例如-native0-native1。我们已经知道使用双破折号来阻止argparse寻找更多选项的技巧。以下调用:

./test.py pos -- -native0 -native1
Run Code Online (Sandbox Code Playgroud)

产生预期的解析参数:

Namespace(bar=False, foo=False, native_arg=['-native0', '-native1'], positional='pos')
Run Code Online (Sandbox Code Playgroud)

但是,尝试在第一个位置参数后添加选项不起作用。更具体地说,以下调用:

./test.py pos --foo -- -native0 -native1
Run Code Online (Sandbox Code Playgroud)

产生以下输出:

usage: [...shortened...]
test.py: error: unrecognized arguments: -- -native0 -native1
Run Code Online (Sandbox Code Playgroud)

将可选参数放在位置之前:

./test.py --foo pos -- -native0 -native1
Run Code Online (Sandbox Code Playgroud)

似乎可以工作,因为打印了以下内容:

Namespace(bar=False, foo=True, native_arg=['-native0', '-native1'], positional='pos')
Run Code Online (Sandbox Code Playgroud)

更奇怪的是,改变的值nargsnative_arg,以'+'在所有上述情况作品(需要提醒的,当然,至少有一个native_arg预期)。

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

Set*_*ton 6

argparse当您将非必需的位置参数与可选参数混合使用时,确实会遇到困难(有关错误报告的详细信息,请参阅/sf/answers/3304610781/)。我将提出一种替代方法,而不是提出解决此问题的方法。

您应该查看parse_known_args为您描述的情况创建的方法(即将选项传递给包装工具)。

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'])
Run Code Online (Sandbox Code Playgroud)

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

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