9

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

import argparse
p = argparse.ArgumentParser()
p.add_argument('--arg', action='store_true')
s = p.add_subparsers()
s.add_parser('test')

将有p.parse_args('--arg test'.split())工作,
但在p.parse_args('test --arg'.split()).

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

4

5 回答 5

5

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

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

编辑:正如@hpaulj 在评论中指出的那样,还有一个parents参数可以传递给ArgumentParser构造函数或add_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

更多示例/文档:

寻找在python中给出命令行参数的最佳方式,其中一些参数是某些选项的req,而一些参数是其他选项的req

Python argparse - 向多个子解析器添加参数(我不确定这个问题是否与这个问题重叠太多)

http://docs.python.org/dev/library/argparse.html#parents

于 2013-08-29T17:19:02.523 回答
5

试试 docopt

>>> 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}
于 2012-06-05T13:39:58.413 回答
3

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

  • opster —我认为这就是 mercurial 的用途,IIRC
  • docopt——这个是新的,但使用了一种有趣的方法
  • 悬崖— 这是 Doug Hellmann(PSF 成员,virtualenvwrapper 作者,普通黑客非凡)的一个相对较新的项目,它不仅仅是一个参数解析器,而是从头开始设计用于处理多级命令
  • clint — 另一个旨在成为“参数解析和更多”的项目,这个项目是由 Kenneth Reitz (来自 Requests 名声)。
于 2012-06-05T11:52:35.730 回答
2

这是一个肮脏的解决方法-

import argparse
p = argparse.ArgumentParser()
p.add_argument('--arg', action='store_true')
s = p.add_subparsers()
s.add_parser('test')

def my_parse_args(ss):
    #parse the info the subparser knows about; don't issue an error on unknown stuff
    namespace,leftover=p.parse_known_args(ss) 
    #reparse the unknown as global options and add it to the namespace.
    if(leftover):
        s.add_parser('null',add_help=False)
        p.parse_args(leftover+['null'],namespace=namespace)

    return namespace

#print my_parse_args('-h'.split())  #This works too, but causes the script to stop.
print my_parse_args('--arg test'.split())
print my_parse_args('test --arg'.split())

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

但是,我认为这是使用子解析器的一种非标准方式。一般来说,全局选项应该出现在子解析器选项之前,而不是之后。

于 2012-06-05T11:46:16.263 回答
1

解析器有一个特定的语法: command <global options> subcommand <subcommand ptions>,你试图给子命令提供一个选项,但你没有定义一个。

于 2012-06-05T11:47:52.540 回答