【问题标题】:argparser and sup parsersargparse 和 sup 解析器
【发布时间】:2013-12-07 02:16:49
【问题描述】:

当我们使用 add_parser 时,函数会构建并返回一个 Parser 对象,有什么方法可以对已经构建的 Parser 对象做同样的事情?

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

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

【问题讨论】:

  • 为什么不将add_parser返回的解析器传递给初始化它的方法,而不是在那个方法中创建呢?
  • 是的,我想过,但我发现它不太优雅,不是吗?
  • @user1595929 也许你是,但我不是。我认为这是一个优雅的解决方案。

标签: python argparse


【解决方案1】:

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

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

并且在你的模块/对象中有一个add_arguments() 方法:

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

【讨论】:

    【解决方案2】:

    这就是我喜欢在我的命令行工具 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
    

    【讨论】:

      【解决方案3】:

      我有点不清楚您需要什么,但可能是创建子解析器时所发生情况的概述会有所帮助。

      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 是一个相关的错误问题。

      如果子解析器只需要一个额外的方法(或现有方法的定制版本),有几种方法可以做到:

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

      Python: changing methods and attributes at runtime 之类的主题讨论了更改实例方法的来龙去脉。

      【讨论】:

        猜你喜欢
        • 2017-12-02
        • 2018-12-31
        • 2014-08-31
        • 2012-04-25
        • 2015-07-17
        • 2018-01-04
        • 2020-09-03
        • 2013-12-21
        • 2013-10-07
        相关资源
        最近更新 更多