【问题标题】:nargs depending on another setting?nargs 取决于另一个设置?
【发布时间】:2020-05-12 21:20:19
【问题描述】:

我正在尝试编写一个支持任意位操作的程序:位图的 AND、OR、NOT 和 COUNT。用法是您运行 program.py --and f1.bit f2.bit 并将结果打印到标准输出。

问题是我希望解析器处理所有警告。具体来说,我希望 nargs 取决于设置的模式 - 如果设置为 COUNT 或 NOT,则需要一个文件,如果设置为 OR 或 AND,则需要两个文件。这是一些(非工作)示例代码:

#!/usr/bin/env python

import argparse

def main(mode, fnames):
    pass

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-O', '--or',
        nargs=2,
        action='store_const', const='or'
    )
    args = parser.parse_args()

    import pprint
    pprint.pprint(args.__dict__)

    #main(**args.__dict__)

我得到的错误是:

Traceback (most recent call last):
  File "bitmaptool.py", line 12, in <module>
    action='store_const', const='or'
  File "/usr/lib/python3.7/argparse.py", line 1362, in add_argument
    action = action_class(**kwargs)
TypeError: __init__() got an unexpected keyword argument 'nargs'

注释掉nargs 有帮助,留下nargs 但注释掉action 也有帮助 - 但我两者都想要。我需要手动实现它还是有什么技巧或其他库可以让我到达那里?

编辑我想通过显示我需要手动编写的代码来阐明我在寻找什么:

if __name__ == '__main__':
    parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)
    parser.add_argument('-O', '--or', nargs=2)
    parser.add_argument('-A', '--and', nargs=2)
    parser.add_argument('-M', '--minus', nargs=2)
    parser.add_argument('-C', '--count', nargs=1)
    parser.add_argument('-N', '--not', nargs=1)
    parser.add_argument('-o', '--output', default='/dev/stdout')
    args = parser.parse_args().__dict__

    mode = None
    files = []
    for current_mode in ['or', 'and', 'not', 'count']:
        if current_mode in args:
            if mode is not None:
                sys.exit('ERROR: more than one mode was specified')
            mode = current_mode
            files = args[mode]

    if mode is None:
        sys.stderr.write('ERROR: no mode was specified\n\n')
        parser.print_help()
        sys.exit(1)

    import pprint
    pprint.pprint(args)

有没有更优雅的方式到达那里?

【问题讨论】:

  • @DJSchaffner 不,没有帮助。不过这也没有什么意义 - 请记住,kwargs 可以按任何顺序出现,只要它们在 args 之后。
  • store_constnargs 设置为0,因此您无法添加自己的值。但是当参数的标志是'--or'时,为什么要存储“或”字符串。你不想args.or=="or" 是吗?
  • @hpaulj 我希望能够做到program.py --or f1.bit f2.bit 并将mode="or" 和文件名存储在其他地方
  • Argparse 会将其存储为(以字典形式){'or': ['f1.bit','f2.bit']}。 'or' 是key,一个名称列表的值。
  • 您也可以使用subcommands 方法,如文档中所述。

标签: python command-line argparse


【解决方案1】:

store_const 从不 获取参数,它实际上将您所说的内容存储为constNone。因为它是一个常数,而不是一个变量。来自argparse's action documentation,重点是我的:

'store_const' - 存储由 const 关键字参数指定的值'store_const' 操作最常与指定某种标志的可选参数一起使用。

您应该将操作更改为实际存储传递的文件名的内容。根据argparse's nargs documentation 和示例,您实际上根本不需要指定action,默认(action='store')就足够了。

文档示例:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', nargs=2) #this line
>>> parser.add_argument('bar', nargs=1)
>>> parser.parse_args('c --foo a b'.split())
Namespace(bar=['c'], foo=['a', 'b'])

EDIT 用于问题的编辑版本 - mutually exclusive group 将确保仅指定一个参数(当然来自该组):

if __name__ == '__main__':
    parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)
    parser.add_argument('-o', '--output', default='/dev/stdout')

    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument('-O', '--or', nargs=2)
    group.add_argument('-A', '--and', nargs=2)
    group.add_argument('-M', '--minus', nargs=2)
    group.add_argument('-C', '--count', nargs=1)
    group.add_argument('-N', '--not', nargs=1)

    args = parser.parse_args().__dict__

    import pprint
    pprint.pprint(args)

【讨论】:

  • 我修改了我的问题以澄清我在寻找什么。我希望它现在可以解释为什么不幸的是您的解决方案似乎还不够。为混乱道歉!
  • 您的“指定了更多模式的那个”= 互斥组 - docs.python.org/3/library/argparse.html#mutual-exclusion ;) 与 required=True 确保您从该组中获得恰好一个参数
  • 很好,只剩下以下部分:mode = None; for current_mode in ['or', 'and', 'not', 'count']: if current_mode in args: mode = current_mode。我认为在 argparse 中不可能像现在这样?
  • 通过你所做的事情,你会得到一本字典,对吧?键是参数,值是……嗯,值。我们修复了这个问题,以便我们总是得到两个参数(output 和所需的操作)及其值。因此,模式实际上是该字典中唯一的键。 ;) mode = [key for key in args if key != 'output'][0] 是一个看起来很奇怪但有效的单线(它实际上过滤掉不是“输出”的键 - 因此只留下我们想要的键)
  • 还有:output = args['output']input_files = args[mode]。现在您有了modeoutputinput_files,您不必再在args 中搜索它们了。 ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-05
  • 1970-01-01
  • 2012-07-15
  • 2013-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多