argparse和sup解析器

时间:2013-12-06 10:26:58

标签: python argparse

当我们使用add_parser时,函数构建并返回一个Parser对象,有没有办法用已经构建的Parser对象做同样的事情?

我想从类中构建对应于该对象的解析器。这样,从主脚本我可以调用一个返回类解析器的类方法,并将其添加到更高级别的解析器来构建最终的命令行。

我该怎么做? 谢谢, 杰罗姆

3 个答案:

答案 0 :(得分:0)

我有点不清楚你需要什么,但可能是你创建subparsers时会发生什么的大纲。

p=argparse.ArgumentParser()

In [3]: sp=p.add_subparsers()

In [4]: sp
Out[4]: _SubParsersAction(option_strings=[], dest='==SUPPRESS==', nargs='A...',
    const=None, default=None, type=None, choices=OrderedDict(), help=None,
    metavar=None)

In [5]: sp._parser_class
Out[5]: argparse.ArgumentParser
In [7]: spp=sp.add_parser('cmd')

In [8]: spp
Out[8]: ArgumentParser(prog='ipython cmd', usage=None, description=None,
    version=None, formatter_class=<class 'argparse.HelpFormatter'>,     
    conflict_handler='error',add_help=True)

sp是位置Action,它采用choices(子分类名称)。它有hidden属性_parser_class,它是用于创建新子分析符的类。

Argparse: how to handle variable number of arguments (nargs='*')提高了改变_parser_class以在子分析符中产生不同行为的可能性。 http://bugs.python.org/issue17204是一个相关的错误问题。

如果subparser只需要一个额外的方法(或现有的方法的自定义版本),有几种方法可以做到:

  • 子类ArgumentParser并使用子类作为解析器(如果解析器不使用新方法,则有效)。
  • 使用上面的讨论来创建一个具有新类
  • 的子分析器
  • 将新方法添加到subparser对象本身。

Python: changing methods and attributes at runtime这样的线程讨论了改变实例方法的细节。

答案 1 :(得分:0)

您可以这样:通常定义您要使用的ArgumentParser,然后将其传递给您的模块:

parser = argparse.ArgumentParser()
some_module.add_arguments(parser)

并在您的模块/对象中使用add_arguments()方法:

def add_arguments(parser):
    parser.add_argument(...)

答案 2 :(得分:0)

我喜欢在命令行工具Python脚本中使用它。

我有一个代表该工具的主类:

class MyToolCommandLineDriver(object):

    @classmethod
    def subcommand_map(cls):
        # create a mapping of subcommand names to classes
        return subcommand_map

    @classmethod
    def run(cls):
        subcommand_map = cls.subcommand_map()

        parser = argparse.ArgumentParser(description='Some Tool')
        parser.add_argument('--some_global_option', help='Some Help')

        subparsers = parser.add_subparsers(title='Subcommands', dest='subcommand_name')
        for subcommand_name, subcommand_class in subcommand_map.items():
            subparser = subparsers.add_parser(subcommand_name, help=subcommand_class.__doc__)
            subcommand_class.configure_argument_parser(subparser)

if __name__ == "__main__":
    MyToolCommandLineDriver.run()

每个subcommand_class项都来自一个公共基类,并有机会配置自己的解析器:

class AbstractSubcommand(object):

    @classmethod
    def configure_argument_parser(cls, parser):
        pass

class SubcommandFooBar(AbstractSubcommand):

    @classmethod
    def configure_argument_parser(cls, parser):
        parser.add_argument('some_argument', nargs='+', help='Some help')

您可以在此处查看完整示例:https://github.com/liyanage/git-tools/blob/master/githelper/githelper.py

这是我制作的基于子命令的工具。此设置允许每个子命令定义其特定的参数,并且它还在顶层生成免费的有用用法消息:

$ githelper.py -h
usage: githelper.py [-h] [--root_path ROOT_PATH] [--verbose]

    {status,reset-master-to-svn-branch,svn-conflicts,clone-externals,tree,svn-lineage,svn-diff,branch,each,svn-delete-resolve,svn-mergeinfo,svn-rebase,foo,checkout}

并为每个子命令:

$ githelper.py clone-externals -h
usage: githelper.py clone-externals [-h] svn_url checkout_directory

positional arguments:
  svn_url             The toplevel SVN repository to clone
  checkout_directory  The path to the sandbox directory to create