2017-02-08 3 views
1

Я хочу, чтобы пользователь предоставил конфигурационный параметр, указав в качестве аргумента 4-значное число. Каждая цифра соответствует состоянию True или False для конкретной установки A, B, C, или D.Синтаксический анализатор командной строки 4-значного числа в качестве аргумента со многими комбинациями (Python)

A B C D 
    0 1 0 0 # would indicate that the user wants B setting only 
    1 1 0 1 # would indicate that the user wants the A, B and D settings 

Существует 16 таких комбинаций параметров.

Затем я буду принимать этот аргумент и обрабатывать его по буквам.

Я думал, что-то вроде этого, где я заявляю, все допустимые значения:

import argparse 

argparser = argparse.ArgumentParser(
    description= "blah blah" 
) 

argparser.add_argument(
    "-cs", "configuration_setting", 
    choices=["1111", "1110", ..., "0001", "0000"] # all 16 combinations 
    dest="config_setting" 
) 

есть ли более эффективный (или более «вещий») подход к обработке всех 16 возможных choices? Должен ли я использовать choices, а просто получить 3-буквенный ввод, а затем обработать его? Обратите внимание, что меня интересует, как проверить, что пользователь предоставил допустимый ввод.

+0

Почему бы вам не указать пользователю каждый вариант отдельно? Чтобы включить тип 'A'' -A' и т. Д. Таким образом, каждый параметр конфигурации может иметь свое собственное описание, и, поскольку вы разбиваете двоичную строку вручную в любом случае, она не добавляет слишком много накладных расходов. – Wombatz

+0

'choice' эффективен, поскольку все, что он делает, это тест' in choice'. Но посмотрели ли вы на дисплей справки? Альтернативы - это пользовательская функция 'type', или post parsing testing. Все они «пифонические». – hpaulj

ответ

1

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

Шестнадцатилетний-элемент жестко закодированы список не является чрезмерным, но вы можете создать свой список, как этот

['{:04b}'.format(i) for i in range(16) ] 

Больше вещий? Не уверен, что в этом случае, но, безусловно, так, если бы это было

['{:07b}'.format(i) for i in range(128) ] 
0

Вы можете также использовать простой цикл, который обеспечит вам гораздо больше гибкости в долгосрочной перспективе. Следующий за контур выдает многомерный список нулей и единиц:

# Part 1, Creating the multidimensional lists: 

data = { 
     'A':[True,False], 
     'B':[True,False], 
     'C':[True,True], 
     'D':[False,True] 
     } 

config = { 'A':[], 
      'B':[], 
      'C':[], 
      'D':[]} 

# Part 2, Building the for-loop which appends the values to the list 

abcd = ["A","B","C","D"] 

for user in range(len(data["A"])): #range(len(data[A])) gives the number of users in the database 
    for letter in abcd: 
     if data[letter][user] == True: 
      config[letter].append(0) 
     else: 
      config[letter].append(1) 

print (config) 
0

Если определить type функции, как:

def forbool(astr): 
    choices = [''.join(x) for x in product(['0','1'],repeat=4)] 
    if astr in choices: 
     return astr 
    else: 
     raise argparse.ArgumentTypeError('your message') 

Она должна возвращать некоторое значение, если astr является действительным, а также повысить ошибка, если нет. Здесь я возвращаю строку непосредственно, но она может быть преобразована в число или список или что вам нравится.

foobool мог бы написать TypeError или ValueError, но ArgumentTypeError позволяет установить сообщение об ошибке.

Он используется как

parser=argparse.ArgumentParser() 
parser.add_argument('--cs', type=forbool, help='value like 0101') 

parser.parse_args(['--cs','0100']) 
Out[26]: Namespace(cs='0100') 

In [27]: parser.parse_args(['--cs','0103']) 
usage: ipython3 [-h] [--cs CS] 
ipython3: error: argument --cs: your message 

In [28]: parser.parse_args(['--cs','01001']) 
usage: ipython3 [-h] [--cs CS] 
ipython3: error: argument --cs: your message 

С choices ошибка выглядит

parser.add_argument('-f', choices=choices, help='value like 0101') 
In [32]: parser.parse_args(['-f','01001']) 
usage: ipython3 [-h] [--cs CS] 
       [-f {0000,0001,0010,0011,0100,0101,0110,0111,1000,1001,1010,1011,1100,1101,1110,1111}] 
ipython3: error: argument -f: invalid choice: '01001' (choose from '0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111', '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111') 

Функционально использование choices является эффективным (но нам не нужно беспокоиться об эффективности с argparse), но ошибка использования/help/становится довольно беспорядочной, когда список длинный. A metavar дает вам контроль над использованием и помощью, но сообщение об ошибке еще долго.

Там нет ничего плохого делать тестирование потом, как с:

if args.cs is not None: 
    try: 
     cs = forbool(args.cs) 
    except argparse.ArgumentTypeError(): 
     parser.error('your message') 

Вызов parser.error... вопросы usage наряду с сообщением об ошибке.

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