【问题标题】:Getting the remaining arguments in argparse在 argparse 中获取剩余的参数
【发布时间】:2014-05-16 00:45:01
【问题描述】:

我想一次得到所有剩余的未使用的参数。我该怎么做?

parser.add_argument('-i', action='store', dest='i', default='i.log')
parser.add_argument('-o', action='store', dest='o', default='o.log')

【问题讨论】:

  • 我不太明白你在问什么。你想要所有的命令行参数都没有被 argparse 解析吗?
  • 我想获取所有参数,我不使用'parser.add_arguments'。它类似于 switch 中的默认值

标签: python argparse


【解决方案1】:

使用parse_known_args():

args, unknownargs = parser.parse_known_args()

【讨论】:

  • 当未知参数可能有前导破折号时,这很有帮助。例如,您将它们传递给另一个脚本。
  • 如果您想允许将冲突的参数名称传递给您正在包装的命令,例如在 docker-compose-wrapper.py --helpdocker-compose-wrapper.py exec --help 中,则此操作无效
  • 似乎有两种解决方案可以为包装命令提取可能冲突的参数:1) 使用 argparse.REMAINDER 在最后一个已知/预期之后收集剩余参数,或 2) 用 @ 分隔包装命令987654328@在命令行。
  • 当你想将 args 转发给其他东西时这很有用
  • 当您希望参数具有需要--argument break 时,请使用argparse.REMAINDER。当您想要透明地使用多个 ArgumentParsers(例如接受参数的共享库)时,请使用 .parse_known_args
【解决方案2】:

使用argparse.REMAINDER:

parser.add_argument('rest', nargs=argparse.REMAINDER)

例子:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-i', action='store', dest='i', default='i.log')
parser.add_argument('-o', action='store', dest='o', default='o.log')
parser.add_argument('rest', nargs=argparse.REMAINDER)
parser.parse_args(['hello', 'world'])
>>> Namespace(i='i.log', o='o.log', rest=['hello', 'world'])

【讨论】:

  • 这是 IMO 包装另一个命令的最佳解决方案:wrapper.py --help --> 您的帮助文本 wrapper.py some args --help --> 传递给包装的命令
  • 这仍然会引发带有可选(指定)参数和以“--”开头的“剩余”参数的异常。如果用 -- 分隔额外的 args,则不会发生异常,但这与使用 nargs="*" 的行为相同。
  • 这很好用,但答案中的链接 (link) 已损坏,因为不再有专门的 argparse.REMAINDER 部分。事实上,argparse.REMAINDER 在整个页面上只被提及一次,并且以不相关的方式出现。这是否等同于 argparse.REMAINDER 未被记录,并且现在是非官方的?
  • argparse.REMAINDER 现在没有记录并被认为是遗留的,但我不相信它会很快被删除。见github.com/python/cpython/pull/18661
  • 现在argparse.REMAINDER这里只提到docs.python.org/3/library/argparse.html#intermixed-parsing
【解决方案3】:

我去编写了三个作为答案给出的建议。测试代码出现在这个答案的底部。结论:目前为止最好的全能答案是nargs=REMAINDER,但这可能真的取决于您的用例。

以下是我观察到的差异:

(1) nargs=REMAINDER 在用户友好性测试中获胜。

$ python test.py --help
Using nargs=*          : usage: test.py [-h] [-i I] [otherthings [otherthings ...]]
Using nargs=REMAINDER  : usage: test.py [-h] [-i I] ...
Using parse_known_args : usage: test.py [-h] [-i I]

(2) nargs=* 悄悄地过滤掉命令行中的第一个 -- 参数,这看起来很糟糕。另一方面,所有方法都尊重--,以此表示“请不要再将这些字符串解析为已知参数。”

$ ./test.py hello -- -- cruel -- -- world
Using nargs=*          : ['hello', '--', 'cruel', '--', '--', 'world']
Using nargs=REMAINDER  : ['hello', '--', '--', 'cruel', '--', '--', 'world']
Using parse_known_args : ['hello', '--', '--', 'cruel', '--', '--', 'world']

$ ./test.py -i foo -- -i bar
Using nargs=*          : ['-i', 'bar']
Using nargs=REMAINDER  : ['--', '-i', 'bar']
Using parse_known_args : ['--', '-i', 'bar']

(3) 除parse_known_args 之外的任何方法如果尝试解析以- 开头的字符串并且结果无效,则该方法将死亡。

$ python test.py -c hello
Using nargs=*          : "unrecognized arguments: -c" and SystemExit
Using nargs=REMAINDER  : "unrecognized arguments: -c" and SystemExit
Using parse_known_args : ['-c', 'hello']

(4) nargs=REMAINDER 在遇到第一个未知参数时完全停止解析。 parse_known_args 将吞噬“已知”的参数,无论它们出现在行中的什么位置(如果它们看起来格式不正确,则会死掉)。

$ python test.py hello -c world
Using nargs=*          : "unrecognized arguments: -c world" and SystemExit
Using nargs=REMAINDER  : ['hello', '-c', 'world']
Using parse_known_args : ['hello', '-c', 'world']

$ python test.py hello -i world
Using nargs=*          : ['hello']
Using nargs=REMAINDER  : ['hello', '-i', 'world']
Using parse_known_args : ['hello']

$ python test.py hello -i
Using nargs=*          : "error: argument -i: expected one argument" and SystemExit
Using nargs=REMAINDER  : ['hello', '-i']
Using parse_known_args : "error: argument -i: expected one argument" and SystemExit

这是我的测试代码。

#!/usr/bin/env python

import argparse
import sys

def using_asterisk(argv):
    parser = argparse.ArgumentParser()
    parser.add_argument('-i', dest='i', default='i.log')
    parser.add_argument('otherthings', nargs='*')
    try:
        options = parser.parse_args(argv)
        return options.otherthings
    except BaseException as e:
        return e

def using_REMAINDER(argv):
    parser = argparse.ArgumentParser()
    parser.add_argument('-i', dest='i', default='i.log')
    parser.add_argument('otherthings', nargs=argparse.REMAINDER)
    try:
        options = parser.parse_args(argv)
        return options.otherthings
    except BaseException as e:
        return e

def using_parse_known_args(argv):
    parser = argparse.ArgumentParser()
    parser.add_argument('-i', dest='i', default='i.log')
    try:
        options, rest = parser.parse_known_args(argv)
        return rest
    except BaseException as e:
        return e

if __name__ == '__main__':
    print 'Using nargs=*          : %r' % using_asterisk(sys.argv[1:])
    print 'Using nargs=REMAINDER  : %r' % using_REMAINDER(sys.argv[1:])
    print 'Using parse_known_args : %r' % using_parse_known_args(sys.argv[1:])

【讨论】:

  • 您为我节省了至少一个小时的时间。为什么这部分不在官方文档中? ?‍♀️
  • 这是 IMO 的最佳答案。
【解决方案4】:

另一种选择是向解析器添加位置参数。指定不带前导破折号的选项,argparse 将在没有其他选项被识别时查找它们。 这具有改进命令帮助文本的额外好处:

>>> parser.add_argument('otherthings', nargs='*')
>>> parser.parse_args(['foo', 'bar', 'baz'])
Namespace(i='i.log', o='o.log', otherthings=['foo', 'bar', 'baz'])

>>> print parser.format_help()
usage: ipython-script.py [-h] [-i I] [-o O] [otherthings [otherthings ...]]

positional arguments:
  otherthings

optional arguments:
  -h, --help   show this help message and exit
  -i I
  -o O

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-31
    • 1970-01-01
    • 2021-11-15
    • 1970-01-01
    • 2020-11-20
    • 1970-01-01
    • 2014-11-09
    • 1970-01-01
    相关资源
    最近更新 更多