python - Argparse - 不要用 `nargs` 捕获位置参数。

标签 python argparse argument-passing

我正在尝试编写一个函数 wo,您可以通过 argparse 解析可变数量的参数 - 我知道我可以通过 nargs="+" 来做到这一点。遗憾的是,argparse 帮助的工作方式(以及人们通常在 CLI 中编写参数的方式)将位置参数放在最后。这导致我的位置参数被捕获为可选参数的一部分。

#!/usr/bin/python
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("positional", help="my positional arg", type=int)
parser.add_argument("-o", "--optional", help="my optional arg", nargs='+', type=float)
args = parser.parse_args()
print args.positional, args.optional

./test.py -h 运行它会显示以下使用说明:

usage: test.py [-h] [-o OPTIONAL [OPTIONAL ...]] positional

但是如果我运行 ./test.py -o 0.21 0.11 0.33 0.13 100 给我

test.py: error: too few arguments

为了正确解析 args,我必须运行 ./test.py 100 -o 0.21 0.11 0.33 0.13

那么我该如何:

  • 使 argparse 重新格式化使用输出,以减少误导,或者甚至更好:

  • 如果可选参数 -o 是列表中的最后一个元素,则告诉 argparse 不要捕获最后一个元素

?

最佳答案

有一个错误报告:http://bugs.python.org/issue9338

argparse optionals with nargs='?', '*' or '+' can't be followed by positionals

一个简单的(用户)修复方法是使用 -- 将 postionals 与 optionals 分开:

./test.py -o 0.21 0.11 0.33 0.13 -- 100

我写了一个补丁,保留了一些参数供位置使用。但这不是微不足道的。

至于改变用法行——最简单的是自己写,例如:

usage: test.py [-h] positional [-o OPTIONAL [OPTIONAL ...]]
usage: test.py [-h] [-o OPTIONAL [OPTIONAL ...]] -- positional

我不建议向用法格式化程序添加逻辑来进行此类更改。我认为它会变得太复杂。

另一个快速解决方法是将此位置转换为(必需)可选。它为用户提供了关于他们的订单的完全自由,并可能减少混淆。如果您不想混淆“必需的可选”,只需给它一个合乎逻辑的默认值即可。

usage: test.py [-h] [-o OPTIONAL [OPTIONAL ...]] -p POSITIONAL
usage: test.py [-h] [-o OPTIONAL [OPTIONAL ...]] [-p POS_WITH_DEFAULT]

Help_Formatter 的一个简单更改是简单地按照定义的顺序列出参数。修改格式化程序行为的正常方法是将其子类化,并更改一两个方法。这些方法中的大多数都是“私有(private)的”(_ 前缀),因此您这样做时要意识到 future 的代码可能会(缓慢地)发生变化。

在此方法中,actions 是参数列表,按照它们被定义的顺序排列。默认行为是将“optionals”从“positionals”中拆分出来,并在末尾重新组合列表。还有其他代码可以处理需要换行的长行。通常它将位置放在单独的行上。我已经省略了。

class Formatter(argparse.HelpFormatter):
    # use defined argument order to display usage
    def _format_usage(self, usage, actions, groups, prefix):
        if prefix is None:
            prefix = 'usage: '

        # if usage is specified, use that
        if usage is not None:
            usage = usage % dict(prog=self._prog)

        # if no optionals or positionals are available, usage is just prog
        elif usage is None and not actions:
            usage = '%(prog)s' % dict(prog=self._prog)
        elif usage is None:
            prog = '%(prog)s' % dict(prog=self._prog)
            # build full usage string
            action_usage = self._format_actions_usage(actions, groups) # NEW
            usage = ' '.join([s for s in [prog, action_usage] if s])
            # omit the long line wrapping code
        # prefix with 'usage:'
        return '%s%s\n\n' % (prefix, usage)

parser = argparse.ArgumentParser(formatter_class=Formatter) 

这会产生如下用法行:

usage: stack26985650.py [-h] positional [-o OPTIONAL [OPTIONAL ...]]

关于python - Argparse - 不要用 `nargs` 捕获位置参数。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26985650/

相关文章:

JavaScript 可变数量的函数参数

javascript - 在 JavaScript 中采用灵活的参数?

python - 将函数输出作为参数传递给另一个函数

python - 打开/写入删除 txt 文件内容?

python - 如何使用 argparse 将参数传递给 python 函数?

python - 使用 Python urllib 时出现错误

python - 列出图像路径 - 'Namespace' 对象没有属性 '__getitem__'

python - 在 pydoc 中显示 argparse 帮助

python - 使用 requirements.txt 安装时,阻止 pip 在单个包上失败

python - 如何在 Ubuntu 中删除 Python2?