Python argparse:具有可选和位置参数的互斥参数
Python argparse : mutually exclusive arguments with optional and positional argument
我想用 argparse 库得到这个:
PROG --yesterday | begin-date [end-date]
我尝试将互斥和参数组结合起来,但没有成功。
这个程序应该只接受:
PROG --yesterday
PROG 2015-11-12
PROG 2015-11-12 2015-11-15
是否可以用 argparse 做到这一点?
谢谢 hpaulj。查看最终结果:
import argparse
from datetime import datetime
import pytz
def argument_date(str_date):
try:
return datetime.strptime(str_date, "%Y-%m-%d").replace(tzinfo=pytz.utc)
except ValueError as e:
raise argparse.ArgumentTypeError(e)
parser = argparse.ArgumentParser(prog='PROG')
parser.usage = """PROG [-h] [--yesterday | start [end]]"""
parser.add_argument('start', type=argument_date, nargs='?', help='Start date (format YYYY-MM-DD)')
parser.add_argument('end', type=argument_date, nargs='?', help='End date (format YYYY-MM-DD)')
parser.add_argument('--yesterday', action='store_true', help='Only yesterday')
args = parser.parse_args()
if args.yesterday and args.start:
raise parser.error("--yesterday option is not incompatible with start argument")
if not args.yesterday and not args.start:
raise parser.error("--yesterday option or start argument should be filled")
if args.end and (args.start >= args.end):
raise parser.error("end argument should be granter than start")
您最好的选择是在解析后测试值,如果需要,提供您自己的自定义 usage
。
A mutually_exclusive_group 可以使用一个可选的位置,例如
group = parser.add_mutually_exclusive_group()
group.add_argument('-y','--yesterday', action='store_true')
group.add_argument('dates',nargs='?')
我原以为它可以与 nargs='*'
一起使用,但我收到 ValueError: mutually exclusive arguments must be optional
错误。
所以一个可选的位置值有效,但是没有办法将此测试与 2 个可选的位置值一起使用。
parser.add_argument('--yesterday',action='store_true')
parser.add_argument('start',nargs='?')
parser.add_argument('end',nargs='?')
然后测试 args.yesterday
、args.start is None
和 args.end is None
。如果这些的某些组合是错误的,那么提高 parser.error('....')
.
只要您能区分默认值和用户给定的值,解析后的测试就和您可能强制解析器执行的任何操作一样好。
考虑什么样的使用信息对您的用户有意义也是一个好主意。例如
例如:
PROG [--yesterday | [start [end]]]
不是 argparse 可以自动生成的东西。
--yesterday
是多余的,因为它只是将 start_date
设置为昨天的快捷方式。相反,让 "yesterday" 成为 start_date
的允许值。事实上,您可以根据需要概括 datetime
以允许任一参数使用其他缩写。例如:
def argument_date(str_date):
# Not the most efficient to roundtrip like this, but
# fits well with your existing code
now = datetime.datetime.utcnow().date()
if str_date == "yesterday":
str_date = str(now - datetime.timedelta(1))
elif str_date == "today"
str_date = str(now)
try:
return datetime.strptime(str_date, "%Y-%m-%d").replace(tzinfo=pytz.utc)
except ValueError as e:
raise argparse.ArgumentTypeError(e)
完成此操作后,您的代码将变为:
parser = argparse.ArgumentParser(prog='PROG')
parser.add_argument('start', type=argument_date, help='Start date (YYYY-MM-DD, yesterday, today)')
parser.add_argument('end', type=argument_date, nargs='?', help='End date (YYYY-MM-DD, yesterday, today)')
我想用 argparse 库得到这个:
PROG --yesterday | begin-date [end-date]
我尝试将互斥和参数组结合起来,但没有成功。
这个程序应该只接受:
PROG --yesterday
PROG 2015-11-12
PROG 2015-11-12 2015-11-15
是否可以用 argparse 做到这一点?
谢谢 hpaulj。查看最终结果:
import argparse
from datetime import datetime
import pytz
def argument_date(str_date):
try:
return datetime.strptime(str_date, "%Y-%m-%d").replace(tzinfo=pytz.utc)
except ValueError as e:
raise argparse.ArgumentTypeError(e)
parser = argparse.ArgumentParser(prog='PROG')
parser.usage = """PROG [-h] [--yesterday | start [end]]"""
parser.add_argument('start', type=argument_date, nargs='?', help='Start date (format YYYY-MM-DD)')
parser.add_argument('end', type=argument_date, nargs='?', help='End date (format YYYY-MM-DD)')
parser.add_argument('--yesterday', action='store_true', help='Only yesterday')
args = parser.parse_args()
if args.yesterday and args.start:
raise parser.error("--yesterday option is not incompatible with start argument")
if not args.yesterday and not args.start:
raise parser.error("--yesterday option or start argument should be filled")
if args.end and (args.start >= args.end):
raise parser.error("end argument should be granter than start")
您最好的选择是在解析后测试值,如果需要,提供您自己的自定义 usage
。
A mutually_exclusive_group 可以使用一个可选的位置,例如
group = parser.add_mutually_exclusive_group()
group.add_argument('-y','--yesterday', action='store_true')
group.add_argument('dates',nargs='?')
我原以为它可以与 nargs='*'
一起使用,但我收到 ValueError: mutually exclusive arguments must be optional
错误。
所以一个可选的位置值有效,但是没有办法将此测试与 2 个可选的位置值一起使用。
parser.add_argument('--yesterday',action='store_true')
parser.add_argument('start',nargs='?')
parser.add_argument('end',nargs='?')
然后测试 args.yesterday
、args.start is None
和 args.end is None
。如果这些的某些组合是错误的,那么提高 parser.error('....')
.
只要您能区分默认值和用户给定的值,解析后的测试就和您可能强制解析器执行的任何操作一样好。
考虑什么样的使用信息对您的用户有意义也是一个好主意。例如
例如:
PROG [--yesterday | [start [end]]]
不是 argparse 可以自动生成的东西。
--yesterday
是多余的,因为它只是将 start_date
设置为昨天的快捷方式。相反,让 "yesterday" 成为 start_date
的允许值。事实上,您可以根据需要概括 datetime
以允许任一参数使用其他缩写。例如:
def argument_date(str_date):
# Not the most efficient to roundtrip like this, but
# fits well with your existing code
now = datetime.datetime.utcnow().date()
if str_date == "yesterday":
str_date = str(now - datetime.timedelta(1))
elif str_date == "today"
str_date = str(now)
try:
return datetime.strptime(str_date, "%Y-%m-%d").replace(tzinfo=pytz.utc)
except ValueError as e:
raise argparse.ArgumentTypeError(e)
完成此操作后,您的代码将变为:
parser = argparse.ArgumentParser(prog='PROG')
parser.add_argument('start', type=argument_date, help='Start date (YYYY-MM-DD, yesterday, today)')
parser.add_argument('end', type=argument_date, nargs='?', help='End date (YYYY-MM-DD, yesterday, today)')