argparse: изменить количество требуемых позиционных аргументов в зависимости от требуемой опции выбора - PullRequest
0 голосов
/ 13 июля 2020

Я предполагаю, что мое приложение будет иметь два основных режима работы:

  1. Считывать значения из файла и работать с ними
  2. Генерировать значения из диапазона и работать с ними .

Мое приложение будет вызываться как:

myApp.py --type range 1000 2000

или

myApp.py --type from-file /tmp/myfile.csv

И есть несколько дополнительных опций, которые я опускаю для краткости, но они делают актуальным наличие полного процессора аргументов.

Если я выбираю диапазон, мне нужны 2 позиционных параметра, но если я выбираю из файла, мне нужен только один. Можно ли использовать argparse для обеспечения правильного количества позиционных параметров на основе параметра типа? Может быть, "choices" не лучший тип argparse для использования, есть ли лучший способ?

import argparse
parser = argparse.ArgumentParser(description='myApp')

parser.add_argument('--type', '-t', choices=['range', 'from-file'], required=True,
                    help='Generate values from a range or load from a file.')
# Stuff here for argparse to enforce the correct number of positional parameters.

args = parser.parse_args()

Кроме того, есть ли хороший способ (например, встроенный в argparse) сделать так, чтобы " --type "не требуется, но я мог бы запустить свое приложение как:

myApp.py range 1000 2000

или

myApp.py from-file /tmp/myfile.csv

Я бы хотел, чтобы argparse по-прежнему принудительно применял этот 'диапазон' и 'из -file '- единственные допустимые параметры, и эти 2 параметра должны следовать за' диапазоном 'или 1 параметр должен следовать за' from-file '.

EDIT:

I Меня также устраивают следующие вызовы:

myApp.py --range 1000 2000

или

myApp.py --from-file /tmp/myfile.csv

Это может упростить процесс требования 2 vs 1 позиционных параметров. Но тогда я бы хотел, чтобы argparse принудительно указывал, что один из двух параметров был указан, а не оба вместе. Может ли argparse это сделать?

Спасибо

1 Ответ

1 голос
/ 13 июля 2020

Используйте субпарсеры, чтобы указать разные аргументы для каждой подкоманды.

import argparse


parser = argparse.ArgumentParser(description='myApp')
sp = parser.add_subparsers()

range_parser = sp.add_parser('range')
range_parser.add_argument('start')
range_parser.add_argument('end')
range_parser.set_defaults(type='range')

file_parser = sp.add_parser('from-file')
file_parser.add_argument('fname')
file_parser.set_defaults(type='file')


args = parser.parse_args()

if args.type == "range":
    start = args.start
    end = args.end
elif args.type == "from-file":
    # Maybe the file contains two lines, the start
    # and end numbers of the range.
    with open(args.file) as f:
        start = int(f.readline())
        end = int(f.readline())

Затем используйте myApp.py range 1000 2000 или myApp.py from-file /tmp/myfile.csv. args.type сообщит вам, какая подкоманда была выбрана (на основе значения по умолчанию, установленного каждым подпарсером для атрибута type), и каждый аргумент подпарсера добавляется только в том случае, если этот подпарсер используется.

...