【问题标题】:Argparse: how to distinguish between arguments for parsers and subparsersArgparse:如何区分解析器和子解析器的参数
【发布时间】:2012-04-25 06:02:42
【问题描述】:

我想将 python-argparse 与参数和位置参数一起使用。假设我在命令行上有我的脚本(这只是一个简单而愚蠢的例子),这是我到目前为止的代码:

#!/usr/bin/env python
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--verbose', action='store_true')
subparsers = parser.add_subparsers(help='command', dest='command')
cmd1_parser = subparsers.add_parser('command1')
cmd1_parser.add_argument('--verbose', action='store_true')

args = parser.parse_args()

print args

现在我这样称呼这个脚本:

~ $ myscript --verbose command1 --verbose
Namespace(command='command1', verbose=True)

~ $ myscript command1 --verbose
Namespace(command='command1', verbose=True)

~ $ myscript --verbose command1
Namespace(command='command1', verbose=True)

现在你可以看到我总是得到相同的命名空间对象,并且无法区分详细命令是常规参数还是子解析器参数。 但我需要它来分别处理这些参数。 什么是一种简单的方法(以最少的代码工作)来做到这一点?

编辑

我在 Python stdlib 问题跟踪器中提交了一个问题: http://bugs.python.org/issue15327

【问题讨论】:

  • 子问题:我在哪里为 argparse 提交问题?
  • 它在标准库中,所以错误转到bugs.python.org。但是,对于功能请求,您应该使用 python-list 或 python-ideas;见docs.python.org/devguide/communication.html
  • 我认为这是一个很好的问题。似乎子解析器应该(可选地)在命名空间中返回一个命名空间,但显然它们不是那样工作的。此外,我有点惊讶add_subparsers 的 dest 关键字实际上做了一些事情。 (它似乎没有记录在任何地方)

标签: python argparse


【解决方案1】:

将您的子解析器的 add_argument 调用更改为:

cmd1_parser.add_argument('--verbose', action='store_true', dest='cmd1_verbose')

这将导致您的第一个示例返回:

~ $ myscript --verbose command1 --verbose
Namespace(cmd1_verbose=True, command='command1', verbose=True)

【讨论】:

  • 只要没有太多重载的命令行参数,这种方法就可以很好地工作。
  • 我在 add_argument 中添加了一个 metavar-param,这样 argparse-help 就不会打印 CMD1_VERBOSE:cmd1_parser.add_argument('--verbose', action='store_true', dest='cmd1_verbose', metavar='VERBOSE')
【解决方案2】:

这是我一起破解的一些小东西。我几乎可以保证它不是没有错误的,但它在这个简单的测试中有效。

import argparse

class _Action(object):
    def __init__(self,master):
        self.master=master
    def add_parser(self,name,**kwargs):
        self.master.subparsers[name]=subParserEnabler()
        return self.master.subparsers[name]

class subParserEnabler(argparse.ArgumentParser):
    def __init__(self,*args,**kwargs):
        self.subparsers={}
        argparse.ArgumentParser.__init__(self,*args,**kwargs)

    def add_subparsers(self,**kwargs):
        return _Action(self)

    def parse_args(self,args,**kwargs):
        args=list(args)
        for k in self.subparsers.keys():
            if k in args:
                break
        try: 
            i=args.index(k)
            output=argparse.ArgumentParser.parse_args(self,args[:i],**kwargs)
            o1=argparse.Namespace()
            setattr(output,k,o1)
            self.subparsers[k].parse_args(args[i+1:],namespace=o1)
        except:
            output=argparse.ArgumentParser.parse_args(self,args,**kwargs)
        return output

parser = subParserEnabler()
parser.add_argument('--verbose', action='store_true')
subparsers = parser.add_subparsers(help='command',dest='command')
cmd1_parser = subparsers.add_parser('command1')
cmd1_parser.add_argument('--verbose', action='store_false')

args = parser.parse_args("--verbose command1 --verbose".split())
print args

它仍然缺少别名,帮助格式可能是错误的……但至少它提供了我想要的输出。最终,John Gaines Jr 的答案可能比我的要简单得多。

【讨论】:

    猜你喜欢
    • 2015-11-08
    • 2017-12-02
    • 2020-09-26
    • 1970-01-01
    • 1970-01-01
    • 2018-12-31
    • 2014-08-31
    • 2019-04-09
    • 2019-05-04
    相关资源
    最近更新 更多