Python:参数解析器,正确处理子命令的全局选项

Python:参数解析器,正确处理子命令的全局选项,python,parsing,command-line-arguments,argparse,subcommand,Python,Parsing,Command Line Arguments,Argparse,Subcommand,argparse无法处理接收全局选项的子命令: import argparse p = argparse.ArgumentParser() p.add_argument('--arg', action='store_true') s = p.add_subparsers() s.add_parser('test') 将有p.parse_参数('--arg test'.split())work, 但是在p.parse_args('test--arg.split())上失败 有人知道python参

argparse无法处理接收全局选项的子命令:

import argparse
p = argparse.ArgumentParser()
p.add_argument('--arg', action='store_true')
s = p.add_subparsers()
s.add_parser('test')
将有
p.parse_参数('--arg test'.split())
work,
但是在p.parse_args('test--arg.split())上失败


有人知道python参数解析器可以正确处理子命令的全局选项吗?

这里有一个棘手的解决方法--

这是可行的——您可以很容易地修改它以使用
sys.argv
(只需删除拆分字符串“
ss
”)。您甚至可以将
argparse.ArgumentParser
子类化,并将
parse_args
方法替换为
my_parse_args
,然后您将永远不会知道它们之间的区别——尽管子类化来替换单个方法对我来说似乎有些过分


然而,我认为,这是一个有点非标准的方式来使用子Parser。一般来说,全局选项应该位于子parser选项之前,而不是之后。

解析器有一个特定的语法:
命令子命令
,您试图向子命令提供一个选项,但没有定义一个。

Python世界中有大量参数解析lib。以下是我看到的一些,所有这些都应该能够解决您试图解决的问题(基于我上次玩它们时对它们的模糊记忆):

  • -我想这就是mercurial的用途IIRC
  • -这是一个新的,但使用了一个有趣的方法
  • -这是Doug Hellmann(PSF成员,VirtualEnvrapper作者,general hacker extraordinaire)的一个相对较新的项目,它不仅仅是一个参数解析器,而是从头设计来处理多级命令
  • -另一个项目的目标是“参数解析和更多”,这是由Kenneth Reitz(请求成名)完成的

    • 您可以轻松地将此参数添加到两个解析器(主解析器和子命令解析器):

      Edit:正如@hpaulj在评论中指出的那样,还有一个
      parents
      参数,可以传递给
      ArgumentParser
      构造函数或
      add\u parser
      方法。您可以在此值分析器中列出新值分析器的基础

      import argparse
      
      base = argparse.ArgumentParser(add_help=False)
      base.add_argument('--arg', action='store_true')
      
      main = argparse.ArgumentParser(parents=[base])
      subparser = main.add_subparsers().add_parser('test', parents=[base])
      
      print main.parse_args('--arg test'.split()).arg
      print main.parse_args('test --arg'.split()).arg
      
      更多示例/文档:

      (我不确定这个问题是否与这个问题重叠过多)


      你说的“失败”是什么意思?你想发生什么?什么全局选项?失败就像抱怨未知参数一样——argI认为Ronny知道它失败的原因(或者至少他不在乎)——他正在寻找解决方法(使用argparse或其他方法).哇--我没意识到有这么多选择--我想这可能是因为我一直能够说服argparse提交+我做了一个快速的调查,docopt和clint不会做cliff是一件非常奇怪和复杂的事情我不想了解opster看起来很有趣it@Ronny,docopt应该可以工作您可以添加
      [options]
      快捷方式,它允许传递全局选项,而不考虑子命令层次结构。@Ronny,即,如果您指定模式
      my_程序测试[选项]
      my_程序测试[--arg]
      @Ronny,将识别case
      @Ronny,太好了!感谢您的反馈,欢迎提供更多选项。如果有更多选项,可以在
      parent
      解析器中定义它们,并通过
      parents
      参数添加到
      p
      s
      。有一个例子,将同一组选项添加到许多子parser中。@hpaulj-我认为这是更好的答案!我将更新我的回答……在Python 2.7.16上,第二个示例在第一种情况下打印
      False
      ,我认为这根本不是期望的行为?因此,我认为第二种经过编辑的解决方案是不正确的。
      >>> from docopt import docopt
      
      >>> usage = """
      ... usage: prog.py command [--test]
      ...        prog.py another [--test]
      ... 
      ... --test  Perform the test."""
      
      >>> docopt(usage, argv='command --test')
      {'--test': True,
       'another': False,
       'command': True}
      
      >>> docopt(usage, argv='--test command')
      {'--test': True,
       'another': False,
       'command': True}
      
      import argparse                                                                  
      
      main = argparse.ArgumentParser()                                                    
      subparser = main.add_subparsers().add_parser('test')                                        
      
      for p in [main,subparser]:                                                                  
         p.add_argument('--arg', action='store_true')                                 
      
      print main.parse_args('--arg test'.split()).arg                                     
      print main.parse_args('test --arg'.split()).arg
      
      import argparse
      
      base = argparse.ArgumentParser(add_help=False)
      base.add_argument('--arg', action='store_true')
      
      main = argparse.ArgumentParser(parents=[base])
      subparser = main.add_subparsers().add_parser('test', parents=[base])
      
      print main.parse_args('--arg test'.split()).arg
      print main.parse_args('test --arg'.split()).arg