python - 在 argparse 中使用 GNU 风格的长选项(不要将可选参数与位置混淆)

标签 python argparse

例如 GNU ls您可以使用 --color[=WHEN] 控制着色选项。现在在这种情况下,等号是至关重要的,因为 ls必须区分 --color 的可选参数和位置参数(这是要列出的文件)。即ls --color列出带有颜色的文件,与 ls --color=always 相同,但是 ls --color always将列出文件 always (还有颜色)。

现在从我所看到的来看argparse似乎使用 --longopt <argument> 接受长选项的参数语法以及这将导致无法使参数可选。也就是说,如果我尝试实现 myls具有与 GNU 相同的行为 ls (这只是一个例子)我现在会遇到问题 myls --color alwaysmyls --color=always 相同(而不是要求 --color 没有参数和 always 作为位置参数)。

我知道我可以使用 myls --color -- always 来规避这个问题,但是如果没有这种解决方法,就没有办法使这项工作有效吗?即告诉argparse --color 的论点必须与 --color[=WHEN] 一起提供句法。

请注意,我不想依赖 --color 的事实选项具有有限数量的有效参数。这是我尝试过但无法正常工作的示例:

import argparse

parser = argparse.ArgumentParser()

parser.add_argument("--foo",
                    action="store",
                    nargs="?")
parser.add_argument("frob",
                    action="store",
                    nargs=argparse.REMAINDER)

print(parser.parse_args(["alpha", "beta"]))
print(parser.parse_args(["--foo", "alpha", "beta"]))
print(parser.parse_args(["--foo=bar", "alpha", "beta"]))

输出:

Namespace(foo=None, frob=['alpha', 'beta'])
Namespace(foo='alpha', frob=['beta'])
Namespace(foo='bar', frob=['alpha', 'beta'])

注意第二个 alpha被解释为 --foo 的参数.我想要:

Namespace(foo=None, frob=['alpha', 'beta'])
Namespace(foo=None, frob=['alpha', 'beta'])
Namespace(foo='bar', frob=['alpha', 'beta'])

最佳答案

您可能已经尝试过 ? optional followed by required positional:

 p=argparse.ArgumentParser()
 p.add_argument('--foo', nargs='?',default='one', const='two')
 p.add_argument('bar')

失败了

In [7]: p.parse_args('--foo 1'.split())
usage: ipython3 [-h] [--foo [FOO]] bar
ipython3: error: the following arguments are required: bar

--foo 消耗了 1,没有给 bar 留下任何东西。

http://bugs.python.org/issue9338讨论这个问题。 nargs='?' 是贪婪的,消耗一个参数,即使下面的位置需要一个。但是建议的补丁很复杂,所以我无法快速将其应用到解析器并测试您的案例。

定义一个可与 --foo==value 一起工作但不消耗 --foo value 中的 value 的想法, 很有趣,但我不知道实现起来需要什么。当然它不适用于当前的解析器。我必须检查它如何处理显式 =

============================

通过更改 parse_args 中的深度嵌套函数,

    def consume_optional(....):
        ....
                # error if a double-dash option did not use the
                # explicit argument
                else:
                    msg = _('ignored explicit argument %r')
                    #raise ArgumentError(action, msg % explicit_arg)
                    # change for stack40989413
                    print('Warn ',msg)
                    stop = start_index + 1
                    args = [explicit_arg]
                    action.nargs=None
                    action_tuples.append((action, args, option_string))
                    break

并添加自定义 Action 类:

class MyAction(myparse._StoreConstAction):
    # requies change in consume_optional
    def __call__(self, parser, namespace, values, option_string=None):
        if values:
            setattr(namespace, self.dest, values)
        else:
            setattr(namespace, self.dest, self.const)

我可以从以下位置获得所需的行为:

p = myparse.ArgumentParser()
p.add_argument('--foo', action=MyAction, const='C', default='D')
p.add_argument('bar')

基本上,我正在修改 store_const 以保存 =explicit_arg(如果存在)。

我不打算将此作为正式补丁提出,但如果它有用,我欢迎提供反馈。使用风险自负。 :)

关于python - 在 argparse 中使用 GNU 风格的长选项(不要将可选参数与位置混淆),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40989413/

相关文章:

python - Django : How to query users based on latest post

python - 在Python中的二维列表(矩阵)的范围内迭代

python - 如何使用库函数 scipy.stats.binom.pmf 返回给定概率的二项分布中的试验次数 (n)?

python - Python 的 argparse 的可选位置参数

Python Argparse : Issue with optional arguments which are negative numbers

python-3.x - 如何修复 "error: the following arguments are required: -i/--image"

Python 名称错误 : name 'file_name' is not defined

python - 如何从 'interact_manual' 更改使用 'ipywidgets' 创建的按钮标签?以及如何更改该按钮的大小和颜色?

python - pip在Mac中给出错误 "pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available."

python - 使用 argparse 选择函数和供应选项