2017-01-25 2 views
2

Я пишу скрипт python, он принимает либо 3 позиционных аргумента (имя, дата, местоположение, скажем), либо 1 аргумент, который является установочным файлом, который содержит эту информацию.скрипт python с 1 или 3 позиционными аргументами

Я знаю, что я могу использовать argparse и я могу сделать позиционные аргументы необязательные с:

parser.add_argument('name_OR_setupFile') 
parser.add_argument('date', nargs='?') 
parser.add_argument('location', nargs='?') 

, а затем я могу проверить ошибки, чтобы убедиться, что пользователь ничего глупого

не делать

Проблема в том, что теперь справочное сообщение будет очень запутанным, потому что неясно, что такое первый аргумент. Мне бы хотелось сделать это как две разные строки add_argument, так или иначе, но я не уверен, как это сделать.

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

Третий вариант заключается в использовании:

parser.add_argument('ARGS', nargs='+', help='ARGS is either of the form setupFile, or name date location') 

, а затем проверка ошибок позже ...

ETA разъяснений:

Я хочу, чтобы иметь возможность вызывать сценарий с либо:

python foo.py setupFile 

или

python foo.py name date location 

Я хочу, чтобы текст справки быть что-то вроде:

usage: 
foo.py setupFile 
foo.py name date location 
+0

Можете ли вы быть более ясно, что вам нужно? вы можете передать справочное сообщение в вызове add_argument? –

+1

FWIW, если я видел 'usage: foo.py [setupFile] [имя даты], моя интерпретация формата args была бы _completely_ отличной от того, что вы описываете. – NPE

+0

@NPE: Хорошая точка. какой формат был бы разумным, как вы думаете? –

ответ

1

Не совсем уверен, что это то, что вы имели в виду, но если я правильно понимаю:

if __name__ =='__main__': 
    def dem_args(*args): 
     if len(args) == 1: 
      if os.path.isfile(args[0]): 
       #go file 
      else: 
       #error regarding this being a bad filename or nonexistent file 
     elif len(args) == 3: 
      #try to process/raise errors regarding name, date, location 
     else: 
      #error reg. wrong number of arguments, possible arguments are either this or that 
3

Я думаю, чистейшее дизайн используя argparse является:

parser = argparse.ArgumentParser() 
g = parser.add_mutually_exclusive_group() 
g.add_argument('--setup','-s',metavar='FILE',help='your help') 
g.add_argument('--name',nargs=3,metavar=('NAME','DATE','LOCATION'),hel 
    ...: p='your help') 

parser.print_help() про Duces:

usage: ipython3 [-h] [--setup FILE | --name NAME DATE LOCATION] 

optional arguments: 
    -h, --help   show this help message and exit 
    --setup FILE, -s FILE 
         your help 
    --name NAME DATE LOCATION 
         your help 

Я обработал требование 1 or 3 аргументов с взаимоисключающим optionals. И использовал metavar, чтобы добавить ясность в аргументы. (Как отмечено в другом недавнем вопросе, metavar не работает с positionals.)

Другой вариант - использовать subparsers. Для этого все еще требуется ключевое слово, например setup и name, только они вводятся без --. И структура справки для подпараллелей совсем другая.

+0

Да, работа с несколькими аргументы важны. но интересно, я не знал о группах! –

0

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

Я действительно решаю дополнительную проблему здесь. Проблема на самом деле немного сложнее, чем я даже указал.Потому что на самом деле есть 3 способа запуска программы, и я хочу иметь параметр --help, чтобы предоставить мне только данные для одного типа. Поэтому я хочу, чтобы -h, -h 1 и -h 2 все делали разные вещи.

Мой текущий код:

import argparse 

baseParser = argparse.ArgumentParser(add_help=False) 
baseParser.add_argument('-f', '--foo', help ='foo argument') 
baseParser.add_argument('-h', '--help', nargs='?' , const = 'all') 

parser1 = argparse.ArgumentParser(parents = [baseParser], add_help=False) 
parser1.add_argument('name', help='name argument (type 1)') 
parser1.add_argument('date', help='date argument') 
parser1.add_argument('location', help='location argument') 

setupParser=argparse.ArgumentParser(parents = [baseParser],add_help=False) 
setupParser.add_argument('setup', help='setup file') 

parser2 = argparse.ArgumentParser(parents = [baseParser],add_help=False) 
parser2.add_argument('name', help='name argument (type 2)') 
parser2.add_argument('baa', help='sheep?') 

realParser = argparse.ArgumentParser(parents=[baseParser], add_help=False) 
realParser.add_argument('ARGS', nargs = '*', help = 'positional arguments') 

args = realParser.parse_args() 
if args.help: 
    if args.help == 'all': 
     print 'This product can be used in multiple ways:' 
     print 'setup' 
     setupParser.print_usage() 
     print 'type1' 
     parser1.print_usage() 
     print'type2' 
     parser2.print_usage() 
     print 'use help [type] for more details' 
    elif args.help=='setup': 
     setupParser.print_help() 
    elif args.help=='1': 
     parser1.print_help() 
    else: 
     parser2.print_help() 
    exit(0) 
    #actually parse the args in args.ARGS, and work with that