argparse:1个参数或参数组之间的必需选择

时间:2018-11-28 15:17:51

标签: python argparse

在我的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:

指定(start, end)不起作用,因为argparse(我想)无法看到我指定了argument_group的{​​{1}}部分而不是mutually_exclusive_group ,并且由于是必需的,因此它会否:

date

我可以通过使common_exclusive_group为不必要来解决此问题,但这显然是不正确的,并且不会捕获没有指定 的情况(因为实际上,

问题2:

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

$ ./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 中的选项周围没有(option_1 | option_2),如果我没有嵌套的组,就会有mutually_exclusive_group

此外,甚至没有显示startend的帮助。

$ ./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 个答案:

答案 0 :(得分:2)

我不知道如何表达自变量和自变量组之间的选择,但是解决您的问题的简单方法是使用以下代码:

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')

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

答案 1 :(得分:2)

鉴于您的评论,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 ,也可以使事情简单:

args.date

当然,这可能会改变您处理后参数代码的方式,因此,如果您的代码必须要求{{1}},这些解决方案可能对您不适用。