代码之家  ›  专栏  ›  技术社区  ›  Steve Lorimer

argparse:必须在1个参数或参数组之间进行选择

  •  4
  • Steve Lorimer  · 技术社区  · 6 年前

    在我的python应用程序中,我的用户可以选择指定:

    • 一次约会
    • 日期范围(开始、结束)

    我创建了一个嵌套 argument_group 里面 mutually_exclusive_group 以下内容:

    argument_group
    +--- mutually_exclusive_group
         +--- date                 (argument)
         +--- argument_group
              +--- start           (argument)
              +--- end             (argument)
    

    我想向我的用户指出 任何一个 date 小组 (start, end) 是必需的,而且 如果 他们都选择团体( start, end 要求:

    这就是我目前为止所拥有的:

    ap = argparse.ArgumentParser()
    grp = ap.add_argument_group('test dates')
    date_group = grp.add_mutually_exclusive_group(required=True)
    
    date_group.add_argument('--date', help='date (YYYYMMDD)')
    date_range = date_group.add_argument_group('date range')
    
    date_range.add_argument('--start',help='start date (YYYYMMDD)', required=True)
    date_range.add_argument('--end',  help='end date (YYYYMMDD)', required=True)
    

    问题1:

    指定 (开始,结束) 不起作用,因为argparse(我猜)看不到我指定了 参数组 部分 相互排斥的 而不是 日期 ,因为相互排斥的组是 必修的 它驳斥:

    $ ./app.py --start 20180101 --end 20180102
    usage: app.py [-h] --date date --start date --end date
    app.py: error: one of the arguments --date is required
    

    我可以通过让互相排斥的小组来解决这个问题。 不需要的 但这显然是不正确的,在 没有什么 被指定为 ,实际上是必需的)

    问题2:

    不幸的是,上述帮助并不能反映我的意图:

    没有 (option_1 | option_2) 围绕中的选项 相互排斥的 如果我没有一个嵌套的组的话就会有。

    此外,帮助 start end 甚至没有显示。

    $ ./app.py --help
    usage: app.py [-h] --date date --start date --end date
    
    optional arguments:
      -h, --help         show this help message and exit
    
    test dates:
      --date date        date (YYYYMMDD) (default: None)
    

    我想要的是:

    $ ./app.py --help
    usage: app.py [-h] (--date date | --start date --end date)
    
    optional arguments:
      -h, --help         show this help message and exit
    
    test dates:
      --date date        date (YYYYMMDD) (default: None)
      --start date       start date (YYYYMMDD) (default: None)
      --end date         end date (YYYYMMDD) (default: None)
    

    这个怎么表达 必修的 在参数和参数组之间选择?

    2 回复  |  直到 6 年前
        1
  •  2
  •   r.ook    6 年前

    你的意见是 start == end 如果 --date 如果有,我会保持简单,并坚持以下两个论点:

    class DefaultEnd(argparse.Action):
      def __call__(self, parser, namespace, values, option_string=None):
        setattr(namespace, self.dest, values)
        setattr(namespace, 'end', values)
    
    ap = argparse.ArgumentParser()
    ap.add_argument('--start', help='date (YYYYMMDD) Mandatory', action=DefaultEnd, required=True)
    ap.add_argument('--end', help='date (YYYYMMDD) Optional, defaulted to START if not provided')
    

    使用自定义 argparse.Action 它也会违约 --end --start 如果只提供后者:

    optional arguments:
      -h, --help     show this help message and exit
      --start START  date (YYYYMMDD) Mandatory
      --end END      date (YYYYMMDD) Optional, defaulted to START if not provided
    

    因此,如果给出参数:

    args = ap.parse_args(['--start','20100102', '--end', '20121123'])
    # args.start = 20100102
    # args.end   = 20121123
    

    如果不是:

    args = ap.parse_args(['--start','20100102'])
    
    # args.start = 20100102
    # args.end   = 20100102
    

    当然,你也可以保持简单如果你只是操纵 args 解析后跳过自定义 argparse.action 总而言之:

    ap.add_argument('--end', help='date (YYYYMMDD) Optional, defaulted to START if not provided', default=None)
    
    ...
    
    args.end = args.end if args.end else args.start
    

    当然,这可能会改变post args代码的处理方式,因此,如果您的代码必须要求,这些解决方案可能不适用于您。 args.date .

        2
  •  2
  •   FelixGK    6 年前

    我不知道如何在参数和参数组之间表达选择,但解决问题的简单方法是使用以下内容:

    ap = argparse.ArgumentParser()
    grp = ap.add_argument_group('test dates')
    date_group = grp.add_mutually_exclusive_group(required=True)
    
    date_group.add_argument('--date', help='date (YYYYMMDD)')
    date_range = date_group.add_argument('--date-range',
        nargs=2, help='Start and End')
    

    只需将日期范围指定为带有两个参数的单个参数。