2017-01-20 4 views
1

Я только что начал использовать argparse, мой код работает, но я пытаюсь проанализировать различные значения того, как пользователь вводит аргумент.Определение различных форм аргументов аргументов аргументов

В настоящее время это мой код:

def setup_args(): 
    """ 
    Set up args for the tool 
    """ 
    parser = argparse.ArgumentParser(
     description=("Get all file versions of a status in a project"), 
     formatter_class=argparse.RawDescriptionHelpFormatter) 

    # Positional Arguments 
    parser.add_argument('project', 
         type=str, 
         help='Name of the to look into') 

    parser.add_argument('status', 
         type=str, 
         help='Define which status to look into') 

    # Optional Arguments 
    parser.add_argument('-o', 
         '--output', 
         action='store_true', 
         help='Write to output to text file if used') 

if __name__ == "__main__": 
    args = setup_args() 

    # Check the status set 
    status_list = ['Pending', 'Work in Progress', 'Approved', 'Rejected'] 
    if not args.status in site_list: 
     raise ValueError("Please input one of the status : 'Pending', 'Work in Progress', 'Approved', 'Rejected'") 

    output_query(args.project, status, args.client, args.output) 

Как вы можете увидеть в моем main .. Он регистрирует только те имена, статус регистрозависимых, что я определил. Есть ли способы, в которых я также могу сделать свой код зарегистрированным, если они напечатаны небольшими шапками - 'pending', 'work in progress', 'approved', 'rejected' или короткими формами - 'p', 'wip', 'a', 'r'?

Один из пути я могу реализовать это с помощью if..elif..

if args.client == ('pending' or 'p'): 
    args.client = 'Pending' 
elif args.client == ('work in progress' or 'wip'): 
    args.client = 'Work in Progress' 
elif args.client == ('approved' or 'a'): 
    args.client = 'Approved' 
elif args.client == ('rejected' or 'r'): 
    args.client = 'Rejected' 

Хотя это работает, это выглядит немного «скучный» для меня. Если у меня есть несколько аргументов, это означает, что мне нужно будет добавить много if...elif..., которые могут быть непрактичными, если только это не единственный способ. Есть ли лучшее решение, чтобы обойти это?

EDIT:

Это, как я управлял моей командой: python prog.py my_project Pending , но я имею в виде сценариев, где один можно ввести так: python prog.py my_project pending или python prog.py my_project p, обратите внимание, что заглавные буквы P стала маленькой буквой.

+0

Это по существу, как у выходного аргумента у вас есть работы, верно? Можете ли вы просто так сделать? поставьте короткое имя сначала, затем длинную версию – denvaar

ответ

2

Вы могли бы обобщить status проверку с .lower() и ограничение количества символов, которые проверяют.

Например, если определить сокращенный список «выбор», я могу проверить все, что выглядит как большие имена с:

In [239]: choices = ['pend', 'work', 'appr','reje'] 
In [240]: status_list = ['Pending', 'Work in Progress', 'Approved', 'Rejected'] 
In [241]: for wd in status_list: 
    ...:  if wd.lower()[:4] in choices: 
    ...:   print(wd) 
    ...:   
Pending 
Work in Progress 
Approved 
Rejected 

Вы, вероятно, не следует ожидать, что ваш пользователь может ввести полный ' Работа в процессе ". Для этого потребуется котирование. В противном случае оболочка будет разбивать это на 3 строки.

Вариация на этом тесте используется startswith:

for wd in status_list: 
    if any([wd.lower().startswith(n) for n in choices]): 
     print(wd) 

Вы также могли позволить парсеру сделать значение проверки

parser.add_argument('status', 
        # type=str, # default, don't need to add it 
        choices = ['pending', 'work', 'approved', 'rejected'], 
        help='Define which status to look into') 

, который генерирует сообщение об ошибке хорошего, если строка не совпадает. И он включает выбор в помощь. Попробуйте и посмотрите, что произойдет.

Недостатком является то, что он не допускает сокращений или верхнего/нижнего регистра.(Пользовательская функция type может обойти эти ограничения, но это более совершенная техника).

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

Способ использования type является определение немного функции:

def abrev(astr): 
    return astr.lower()[:4] 

, который работает в вышеуказанном тест:

for wd in status_list: 
    if abrev(wd) in choices: 
     print(wd) 

В парсер он может быть использован как:

In [253]: p = argparse.ArgumentParser() 
In [254]: p.add_argument('status', type=abrev, choices=choices); 

In [255]: p.print_help() 
usage: ipython3 [-h] {pend,work,appr,reje} 

positional arguments: 
    {pend,work,appr,reje} 

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

Образцы вызовов:

In [256]: p.parse_args(['Work']) 
Out[256]: Namespace(status='work') 

In [257]: p.parse_args(['status']) 
usage: ipython3 [-h] {pend,work,appr,reje} 
ipython3: error: argument status: invalid choice: 'stat' (choose from 'pend', 'work', 'appr', 'reje') 
... 

In [258]: p.parse_args(['reject']) 
Out[258]: Namespace(status='reje') 

In [259]: p.parse_args(['Pending']) 
Out[259]: Namespace(status='pend') 
+0

классный .. Я думал, что смогу сделать его более универсальным .. Думаю, мне нужно будет подумать о других способах обойти это. Еще мне нужно будет сказать пользователям ввести конкретные ключевые слова – dissidia

+0

Словари другой полезный инструмент для сопоставления из одного набора строк в другие строки или, еще лучше, других объектов. – hpaulj

+0

Хорошо, не знал о применении словаря. Звучит как жизнеспособный вариант использования словаря, а не 'if ... elif ...' – dissidia

0

Хотя я еще не протестировал его, глядя на функциональную документацию add_argument, вы должны добавить их в качестве первых аргументов.

имя или флаги - либо имя, либо список опционных строк, например. foo или -f, --foo.

https://docs.python.org/3/library/argparse.html#the-add-argument-method

+0

. Я обновил свой поток немного подробнее .. исправьте меня, если я ошибаюсь, но не 'имя или флаги ', где вы вводите ввод, в моем случае я фокусирую по имени – dissidia

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