簡體   English   中英

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

一個common_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.yesterdayargs.start is Noneargs.end is None 如果這些組合的某些組合是錯誤的,則引發parser.error('....')

只要您可以區分默認值和用戶給定的值,解析后的測試與您可能強制解析器執行的任何操作一樣好。

考慮什么使用消息對您的用戶來說也是一個好主意。 例如

例如:

PROG  [--yesterday | [start [end]]]

不是argparse可以自動生成的東西。

--yesterday是多余的,因為它只是將start_date設置為昨天的快捷方式。 相反,讓“昨天”為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)')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM