【问题标题】:Hook on arguments in argparse python在 argparse python 中挂钩参数
【发布时间】:2015-08-22 07:29:54
【问题描述】:

我有兴趣将一个类中使用 argparse 解析的额外参数挂钩到另一个类中的另一个方法,该方法已经使用 argparse 模块解析了很少的参数。

Project 1
def x():
    parser = argparse.ArgumentParser()
    parser.add_argument('--abc')

Project 2
def y():
     parser = argparse.ArgumentParser()
     parser.add_argument('--temp1')
     parser.add_argument('--temp2')

当我运行 x() 时,我想将“--abc”参数添加到 y() 的参数列表中,该列表在运行时是“temp1”、“temp2”。继承是最好的方法并相应地定义构造函数吗?有人可以提供一些示例代码 sn-p 吗?

谢谢!

【问题讨论】:

    标签: python inheritance runtime argparse


    【解决方案1】:

    argparse 实现了parents 功能,可让您将一个解析器的参数添加到另一个解析器。检查文档。或调整您的情况:

    parser_x = argparse.ArgumentParser(add_help=False)
    parser_x.add_argument('--abc')
    parser_y = argparse.ArgumentParser(parents=[parser_x])
    parser_y.add_argument('--temp1')
    parser_y.add_argument('--temp2')
    parser_y.print_help()
    

    打印:

    usage: ipython [-h] [--abc ABC] [--temp1 TEMP1] [--temp2 TEMP2]    
    optional arguments:
      -h, --help     show this help message and exit
      --abc ABC
      --temp1 TEMP1
      --temp2 TEMP2
    

    需要add_help=False 以避免parser_x 通常添加的-h 与parser_y 获得的parser_y 之间的冲突。

    另一种方法是让x 将其参数添加到预定义的解析器:

    def x(parser=None):
        if parser is None:
            parser = argparse.ArgumentParser()
        parser.add_argument('--abc')
        return parser
    
    def y():
        ....
        return parser
    
    parsery = y()
    parserx = x(parsery)
    

    知道add_argument 返回对其创建的参数(Action 对象)的引用也可能很有用。

     parser = argparse.ArgumentParser()
     arg1 = parser.add_argument('--abc')
    

    在 shell 中执行此操作,您会看到 arg1 显示为:

     _StoreAction(option_strings=['--abc'], dest='abc', nargs=None,
         const=None, default=None, type=None, choices=None, 
         help=None, metavar=None)
    

    arg1 是一个可以放在列表、字典中的对象。理论上,您甚至可以将其添加到另一个解析器。这实际上就是父母机制所做的事情(即将动作引用从父母复制到孩子)。

    【讨论】:

      【解决方案2】:

      您可以从 Django 的management commands 中获得灵感。它们基本上设置如下:

      • 入口点是run_from_argv,它调用create_parser,解析命令行,提取解析后的参数并提供给execute;
      • create_parser 方法创建一个 argparse 解析器并使用 add_argument 预填充可用于所有命令的默认选项。然后该函数调用该类的add_arguments 方法,该方法旨在被子类重载;
      • execute 方法负责处理与默认选项相关的各种行为。然后它调用handle,这意味着被子类重载以处理add_arguments引入的特定选项。

      您的要求并不完全清楚,但我认为在您的情况下,您不需要打扰执行方法。我会去:

      import argparse
      import sys
      
      class BaseParser:
          def create_parser(self, progname):
              parser = argparse.ArgumentParser(prog=progname)
              parser.add_argument('--temp1')
              parser.add_argument('--temp2')
              self.add_arguments(parser)
              return parser
      
          def add_arguments(self, parser):
              pass # to be optionnally defined in subclasses
      
          def parse_command_line(self, argv):
              parser = create_parser(argv[0])
              options = parser.parse_args(argv[1:])
              parsed_options = vars(options)
              self.handle(**parsed_options) # HAS TO be defined in subclasses
      
      class X(BaseParser):
          def add_arguments(self, parser):
              parser.add_argument('--abc')
      
          def handle(self, **options):
              abc = options['abc']
              temp1 = options['temp1']
              temp2 = options['temp2']
              # do stuff with thoses variables
      
      class Y(BaseParser):
          def handle(self, **options):
              temp1 = options['temp1']
              temp2 = options['temp2']
              # do stuff
      
      x = X()
      y = Y()
      args = sys.argv
      x.parse_command_line(args)
      y.parse_command_line(args)
      

      如果 X 是 Y 的子类,您可以进一步简化代码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-07-12
        • 2018-07-09
        • 2014-07-23
        • 2013-03-31
        • 2015-06-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多