2017-01-09 4 views
1

У меня есть программа под названием program.py, и я использую argparse для разбора аргументов.Python argparse - различные наборы опций

У меня есть два режима, я хочу, чтобы запустить этот бинарный файл с: 1) моделированием, которое не требует никаких аргументов 2) Non-моделирования, которая требует много аргументов

хотят программу либо принять

python program --simulation 

или

python program arg1 arg2 arg3 arg4 

Где все 'аргументах' необходимы.

Единственный способ, который я решил сделать, это добавить 'required = False' ко всем полям и проверить логику вручную, но мне было интересно, есть ли более элегантный способ.

Вот урезанная версия кода У меня есть

def get_args(): 
    parser = argparse.ArgumentParser(description = "program") 
    parser.add_argument("arg1", type = bool) 
    parser.add_argument("arg2" ,type = str) 
    parser.add_argument("arg3", type = int) 
    parser.add_argument("arg4", type = str) 
    parser.add_argument("--simulation") 
    args = parser.parse_args() 
    return args 
+0

Ваше использование 'type = bool' проблематично. См. Ссылку в моем ответе. – hpaulj

ответ

1

argparse не может быть, что умный. Тем не менее, в вашем простом случае, вы могли бы «помочь» ему выбрать правильные параметры для анализа:

def get_args(args=sys.argv[1:]): 
    parser = argparse.ArgumentParser(description = "program") 
    if args and args[0].startswith("--"): 
     parser.add_argument("--simulation") 
    else: 
     parser.add_argument("arg1", type = bool) 
     parser.add_argument("arg2" ,type = str) 
     parser.add_argument("arg3", type = int) 
     parser.add_argument("arg4", type = str) 
    args = parser.parse_args(args=args) 
    return args 

так print(get_args("--simulation xx".split())) выходы:

Namespace(simulation='xx') 

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

и print(get_args("True foo 3 bar".split())) выходы:

Namespace(arg1=True, arg2='foo', arg3=3, arg4='bar') 

забывание одного из 4-х позиционные параметры командной строки не удается синтаксический анализ, как и ожидалось.

BTW, я добавил параметр по умолчанию, который, если пропущено, считывает из системных аргументов (как это было в вашем коде). Кроме того, вы можете читать из текстового файла и передавать токены args. Таким образом, легче протестировать и создавать модули, которые можно вызывать с параметрами из других модулей без необходимости взломать через sys.argv.

+0

Работал чудесно, спасибо! Один быстрый вопрос: нужно ли «args» «get_args»? Или это просто для того, чтобы сохранить его более общим, если мы хотим прочитать аргументы, скажем, из текстового файла? – triplebig

+0

точно, см. Мое редактирование. Передача аргументов не соответствует тому же поведению, что и раньше: parse из командной строки. –

1

Это явно неудобная спецификация для argparse, и я подозреваю большинство других парсеров POSIX.

Сканирование sys.argv и настройка определения парсера является одним из возможных способов.

Другой способ заключается в использовании 2 стадии синтаксического анализа, с parse_known_args:

import argparse 
usage = 'prog [-h] [--simulation] [arg1 arg2 arg3 arg4]' 
parser1 = argparse.ArgumentParser(usage=usage) 
parser1.add_argument('--simulation', action='store_true') 
# or omit the `store_true` if it just takes one argument 
# other possible optionals 

parser2 = argparse.ArgumentParser() 
#parser2.add_argument("arg1", type = bool) # not a valid type parameter 
parser2.add_argument("arg2") 
parser2.add_argument("arg3", type = int) 
parser2.add_argument("arg4") 
# positionals are required, unless nargs=? or * 

args, extras = parser1.parse_known_args() 
if not args.simulation: 
    args = parser2.parse_args(extras, namespace=args) 
elif extras: 
    parser1.error('cannot use --simulation with args') 
print(args) 

Возможные трассы включают в себя:

1526:~/mypy$ python stack41556997.py -h 
usage: prog [-h] [--simulation] [arg1 arg2 arg3 arg4] 

optional arguments: 
    -h, --help show this help message and exit 
    --simulation 

1526:~/mypy$ python stack41556997.py --simulation 
Namespace(simulation=True) 

1527:~/mypy$ python stack41556997.py 1 2 3 
Namespace(arg2='1', arg3=2, arg4='3', simulation=False) 

1527:~/mypy$ python stack41556997.py 1 2 3 --sim 
usage: prog [-h] [--simulation] [arg1 arg2 arg3 arg4] 
stack41556997.py: error: cannot use --simulation with args 

Обратите внимание, что помощь не включает в себя оба набора. Я включил некоторую информацию в пользовательское использование, но нет линий помощи для arg#. Создание хорошего сообщения help будет неудобно с вашей спецификацией.

Я пропустил ваш arg1. type=bool недействителен аргумент type. См. Мое объяснение по адресу Parsing boolean values with argparse

Я изменил --simulation на store_true, так как вы сказали, что не принимали никаких аргументов. Это нормальный способ принять True/False.

Subparsers часто является лучшим инструментом для принятия различных шаблонов аргументов. В этом случае у вас может быть один подпараметр, называемый «имитировать», который не требует каких-либо аргументов, а другой вызов «somethingelse», для которого требуются 4 позиции.

Я собирался предложить взаимную_exclusive_group с --simulation и --other опциями. Но аргумент store_true не работает в такой группе.

=============

subparser маршрут:

parser = argparse.ArgumentParser() 
sp = parser.add_subparsers(dest='cmd') 
sp.add_parser('simulate') 
parser2 = sp.add_parser('other') 
parser2.add_argument("arg2") 
parser2.add_argument("arg3", type = int) 
parser2.add_argument("arg4") 
print(parser.parse_args()) 

испытания:

1552:~/mypy$ python stack41556997.py -h 
usage: stack41556997.py [-h] {simulate,other} ... 

positional arguments: 
    {simulate,other} 

optional arguments: 
    -h, --help  show this help message and exit 
1557:~/mypy$ python stack41556997.py simulate 
Namespace(cmd='simulate') 
1557:~/mypy$ python stack41556997.py other -h 
usage: stack41556997.py other [-h] arg2 arg3 arg4 

positional arguments: 
    arg2 
    arg3 
    arg4 

optional arguments: 
    -h, --help show this help message and exit 
1557:~/mypy$ python stack41556997.py other 1 2 3 
Namespace(arg2='1', arg3=2, arg4='3', cmd='other') 

Обратите внимание, что arg3type преобразовал вклад целое число. Остальные оставлены как строки. С помощью этой настройки args.cmd будет именем подпараметра, не совсем то же самое, что и атрибут boolean args.simulation.

==================

помеченном аргумент не-по умолчанию требуется. Позиционные аргументы требуются, если значение nargs равно?? или '*'. Вы не можете указать «обязательный» параметр для позиционного.

 Смежные вопросы

  • Нет связанных вопросов^_^