Каков наилучший способ анализа аргументов командной строки?

Какой самый простой , сложный и наиболее гибкий метод или библиотека для parsingа аргументов командной строки Python?

Этот ответ предлагает optparse который подходит для более старых версий Python. Для Python 2.7 и выше argparse заменяет optparse . См. Этот ответ для получения дополнительной информации.

Как указывали другие люди, вам лучше идти с optparse over getopt. getopt – это почти однозначное сопоставление стандартных функций библиотеки getopt (3) C и не очень простое в использовании.

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

Вот типичная строка для добавления опции в ваш синтаксический анализатор:

 parser.add_option('-q', '--query', action="store", dest="query", help="query string", default="spam") 

Это в значительной степени говорит само за себя; во время обработки он принимает -q или -query как опции, сохраняет аргумент в атрибуте, называемом query, и имеет значение по умолчанию, если вы его не укажете. Это также самодокументируется тем, что вы объявляете аргумент help (который будет использоваться при запуске с помощью -h / – help) прямо там с опцией.

Обычно вы разбираете свои аргументы с помощью:

 options, args = parser.parse_args() 

По умолчанию будут проанализированы стандартные аргументы, переданные скрипту (sys.argv [1:])

options.query будет установлено значение, которое вы передали скрипту.

Вы создаете парсер просто, делая

 parser = optparse.OptionParser() 

Это все основы, в которых вы нуждаетесь. Вот полный скрипт Python, который показывает это:

 import optparse parser = optparse.OptionParser() parser.add_option('-q', '--query', action="store", dest="query", help="query string", default="spam") options, args = parser.parse_args() print 'Query string:', options.query 

5 строк питона, которые показывают вам основы.

Сохраните его в sample.py и запустите его один раз с помощью

 python sample.py 

и один раз с

 python sample.py --query myquery 

Кроме того, вы обнаружите, что optparse очень легко расширить. В одном из моих проектов я создал class Command, который позволяет легко встраивать подкоманды в дереве команд. Он использует optparse для объединения команд вместе. Это не то, что я могу легко объяснить в нескольких строках, но не стесняйтесь просматривать в моем репозитории для основного classа, а также class, который использует его, и парсер параметров

В других ответах упоминается, что argparse – это путь для нового Python, но не приводят примеры использования. Для полноты, вот краткий обзор того, как использовать argparse:

1) Инициализировать

 import argparse # Instantiate the parser parser = argparse.ArgumentParser(description='Optional app description') 

2) Добавить аргументы

 # Required positional argument parser.add_argument('pos_arg', type=int, help='A required integer positional argument') # Optional positional argument parser.add_argument('opt_pos_arg', type=int, nargs='?', help='An optional integer positional argument') # Optional argument parser.add_argument('--opt_arg', type=int, help='An optional integer argument') # Switch parser.add_argument('--switch', action='store_true', help='A boolean switch') 

3) Разбор

 args = parser.parse_args() 

4) Доступ

 print("Argument values:") print(args.pos_arg) print(args.opt_pos_arg) print(args.opt_arg) print(args.switch) 

5) Проверить значения

 if args.pos_arg > 10: parser.error("pos_arg cannot be larger than 10") 

Применение

Правильное использование:

 $ ./app 1 2 --opt_arg 3 --switch Argument values: 1 2 3 True 

Неправильные аргументы:

 $ ./app foo 2 --opt_arg 3 --switch usage: convert [-h] [--opt_arg OPT_ARG] [--switch] pos_arg [opt_pos_arg] app: error: argument pos_arg: invalid int value: 'foo' $ ./app 11 2 --opt_arg 3 Argument values: 11 2 3 False usage: app [-h] [--opt_arg OPT_ARG] [--switch] pos_arg [opt_pos_arg] convert: error: pos_arg cannot be larger than 10 

Полная помощь:

 $ ./app -h usage: app [-h] [--opt_arg OPT_ARG] [--switch] pos_arg [opt_pos_arg] Optional app description positional arguments: pos_arg A required integer positional argument opt_pos_arg An optional integer positional argument optional arguments: -h, --help show this help message and exit --opt_arg OPT_ARG An optional integer argument --switch A boolean switch 

Использование docopt

С 2012 года Python имеет очень простой, мощный и действительно classный модуль для парсинга аргументов, называемый docopt . Он работает с Python 2.6 до 3.5 и не требует установки (просто скопируйте его). Вот пример, взятый из его документации:

 """Naval Fate. Usage: naval_fate.py ship new ... naval_fate.py ship  move   [--speed=] naval_fate.py ship shoot   naval_fate.py mine (set|remove)   [--moored | --drifting] naval_fate.py (-h | --help) naval_fate.py --version Options: -h --help Show this screen. --version Show version. --speed= Speed in knots [default: 10]. --moored Moored (anchored) mine. --drifting Drifting mine. """ from docopt import docopt if __name__ == '__main__': arguments = docopt(__doc__, version='Naval Fate 2.0') print(arguments) 

Итак, вот оно: 2 строки кода плюс ваша строка документа, что существенно, и вы получаете аргументы, проанализированные и доступные в объекте arguments. Я сказал тебе, что это круто, не я 😉

Использование python-fire

С 2017 года у python-fire есть еще один classный модуль, который может дать интерфейс CLI вашему коду, когда вы выполняете парсинг с нулевым аргументом. Вот простой пример из документации (эта небольшая программа предоставляет функцию double в командной строке):

 import fire class Calculator(object): def double(self, number): return 2 * number if __name__ == '__main__': fire.Fire(Calculator) 

В командной строке вы можете запустить:

 > calculator.py double 10 20 > calculator.py double --number=15 30 

Удивительно, не так ли?

По этой причине новый хип-путь является argparse . argparse> optparse> getopt

update: Начиная с py2.7 argparse является частью стандартной библиотеки, а optparse устарел.

Практически все используют getopt

Вот пример кода для документа:

 import getopt, sys def main(): try: opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="]) except getopt.GetoptError: # print help information and exit: usage() sys.exit(2) output = None verbose = False for o, a in opts: if o == "-v": verbose = True if o in ("-h", "--help"): usage() sys.exit() if o in ("-o", "--output"): output = a 

Итак, одним словом, вот как это работает.

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

sys.argv – это в значительной степени ваш char** argv в C. Как и в C, вы пропускаете первый элемент, который является именем вашей программы, и анализируйте только аргументы: sys.argv[1:]

Getopt.getopt будет анализировать его согласно правилу, которое вы даете в аргументе.

"ho:v" здесь описывает короткие аргументы: -ONELETTER . Параметр : означает, что -o принимает один аргумент.

Наконец ["help", "output="] описывает длинные аргументы ( --MORETHANONELETTER ). Значение = после вывода еще раз означает, что вывод принимает один аргумент.

Результатом является список пары (параметр, аргумент)

Если параметр не принимает никаких аргументов (например, --help здесь), то arg является пустой строкой. Затем вы обычно хотите зациклиться на этом списке и проверить имя параметра, как в примере.

Надеюсь, это вам помогло.

Используйте optparse который поставляется со стандартной библиотекой. Например:

 #!/usr/bin/env python import optparse def main(): p = optparse.OptionParser() p.add_option('--person', '-p', default="world") options, arguments = p.parse_args() print 'Hello %s' % options.person if __name__ == '__main__': main() 

Источник: использование Python для создания инструментов командной строки UNIX

Однако, как и у Python 2.7 optparse, устаревшие, см.: Зачем использовать argparse, а не optparse?

Я предпочитаю Click . Он абстрагирует варианты управления и позволяет «(…) создавать красивые интерфейсы командной строки в виде композиций с минимальным количеством кода».

Вот пример использования:

 import click @click.command() @click.option('--count', default=1, help='Number of greetings.') @click.option('--name', prompt='Your name', help='The person to greet.') def hello(count, name): """Simple program that greets NAME for a total of COUNT times.""" for x in range(count): click.echo('Hello %s!' % name) if __name__ == '__main__': hello() 

Он также автоматически создает хорошо отформатированные страницы справки:

 $ python hello.py --help Usage: hello.py [OPTIONS] Simple program that greets NAME for a total of COUNT times. Options: --count INTEGER Number of greetings. --name TEXT The person to greet. --help Show this message and exit. 

На всякий случай вам может понадобиться, это может помочь, если вам нужно захватить аргументы unicode в Win32 (2K, XP и т. Д.):

 from ctypes import * def wmain(argc, argv): print argc for i in argv: print i return 0 def startup(): size = c_int() ptr = windll.shell32.CommandLineToArgvW(windll.kernel32.GetCommandLineW(), byref(size)) ref = c_wchar_p * size.value raw = ref.from_address(ptr) args = [arg for arg in raw] windll.kernel32.LocalFree(ptr) exit(wmain(len(args), args)) startup() 

Я думаю, что лучший способ для крупных проектов – оппонировать, но если вы ищете простой способ, возможно, http://werkzeug.pocoo.org/documentation/script что-то для вас.

 from werkzeug import script # actions go here def action_foo(name=""): """action foo does foo""" pass def action_bar(id=0, title="default title"): """action bar does bar""" pass if __name__ == '__main__': script.run() 

Таким образом, в основном каждая функция action_ * отображается в командной строке, а бесплатное справочное сообщение генерируется бесплатно.

 python foo.py usage: foo.py  [] foo.py --help actions: bar: action bar does bar --id integer 0 --title string default title foo: action foo does foo --name string 

Я предпочитаю optparse to getopt. Это очень декларативно: вы указываете имена вариантов и эффектов, которые они должны иметь (например, установка логического поля), и он возвращает вам словарь, заполненный в соответствии с вашими спецификациями.

http://docs.python.org/lib/module-optparse.html

consoleargs заслуживает упоминания здесь. Он очень прост в использовании. Проверьте это:

 from consoleargs import command @command def main(url, name=None): """ :param url: Remote URL :param name: File name """ print """Downloading url '%r' into file '%r'""" % (url, name) if __name__ == '__main__': main() 

Теперь в консоли:

 % python demo.py --help Usage: demo.py URL [OPTIONS] URL: Remote URL Options: --name -n File name % python demo.py http://www.google.com/ Downloading url ''http://www.google.com/'' into file 'None' % python demo.py http://www.google.com/ --name=index.html Downloading url ''http://www.google.com/'' into file ''index.html'' 

По умолчанию аргумент командной строки

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

 import sys def get_args(name='default', first='a', second=2): return first, int(second) first, second = get_args(*sys.argv) print first, second 

Аргумент «имя» фиксирует имя сценария и не используется. Результат тестирования выглядит следующим образом:

 > ./test.py a 2 > ./test.py A A 2 > ./test.py A 20 A 20 

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

Вот метод, а не библиотека, которая, похоже, работает на меня.

Цели здесь должны быть краткими, каждый аргумент анализируется одной строкой, строки args для удобочитаемости, код прост и не зависит от каких-либо специальных модhive (только os + sys), изящно предупреждает о отсутствующих или неизвестных аргументах , используйте простой цикл / range () и работайте через python 2.x и 3.x

Показаны два флажка переключения (-d, -v) и два значения, контролируемые аргументами (-i xxx и -o xxx).

 import os,sys def HelpAndExit(): print("<>") sys.exit(1) def Fatal(msg): sys.stderr.write("%s: %s\n" % (os.path.basename(sys.argv[0]), msg)) sys.exit(1) def NextArg(i): '''Return the next command line argument (if there is one)''' if ((i+1) >= len(sys.argv)): Fatal("'%s' expected an argument" % sys.argv[i]) return(1, sys.argv[i+1]) ### MAIN if __name__=='__main__': verbose = 0 debug = 0 infile = "infile" outfile = "outfile" # Parse command line skip = 0 for i in range(1, len(sys.argv)): if not skip: if sys.argv[i][:2] == "-d": debug ^= 1 elif sys.argv[i][:2] == "-v": verbose ^= 1 elif sys.argv[i][:2] == "-i": (skip,infile) = NextArg(i) elif sys.argv[i][:2] == "-o": (skip,outfile) = NextArg(i) elif sys.argv[i][:2] == "-h": HelpAndExit() elif sys.argv[i][:1] == "-": Fatal("'%s' unknown argument" % sys.argv[i]) else: Fatal("'%s' unexpected" % sys.argv[i]) else: skip = 0 print("%d,%d,%s,%s" % (debug,verbose,infile,outfile)) 

objective NextArg () состоит в том, чтобы возвращать следующий аргумент при проверке отсутствующих данных, а «skip» пропускает цикл, когда используется NextArg (), сохраняя parsing флагов до одного лайнера.

Код Argparse может быть длиннее фактического кода реализации!

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

Относительный новоприбывший к синтаксическому сценарию аргумента (я думаю) – plac .

Он делает некоторые признанные компромиссы с argparse, но использует встроенную документацию и обтекает просто функцию функции типа main() :

 def main(excel_file_path: "Path to input training file.", excel_sheet_name:"Name of the excel sheet containing training data including columns 'Label' and 'Description'.", existing_model_path: "Path to an existing model to refine."=None, batch_size_start: "The smallest size of any minibatch."=10., batch_size_stop: "The largest size of any minibatch."=250., batch_size_step: "The step for increase in minibatch size."=1.002, batch_test_steps: "Flag. If True, show minibatch steps."=False): "Train a Spacy (http://spacy.io/) text classification model with gold document and label data until the model nears convergence (LOSS < 0.5)." pass # Implementation code goes here! if __name__ == '__main__': import plac; plac.call(main) 

Я расширил подход Erco, чтобы разрешить необходимые позиционные аргументы и необязательные аргументы. Они должны предшествовать аргументам -d, -v и т. Д.

Позиционные и необязательные аргументы могут быть получены с помощью PosArg (i) и OptArg (i, по умолчанию) соответственно. При обнаружении необязательного аргумента начальная позиция поиска параметров (например, -i) перемещается на 1 вперед, чтобы избежать «неожиданного» фатального.

 import os,sys def HelpAndExit(): print("<>") sys.exit(1) def Fatal(msg): sys.stderr.write("%s: %s\n" % (os.path.basename(sys.argv[0]), msg)) sys.exit(1) def NextArg(i): '''Return the next command line argument (if there is one)''' if ((i+1) >= len(sys.argv)): Fatal("'%s' expected an argument" % sys.argv[i]) return(1, sys.argv[i+1]) def PosArg(i): '''Return positional argument''' if i >= len(sys.argv): Fatal("'%s' expected an argument" % sys.argv[i]) return sys.argv[i] def OptArg(i, default): '''Return optional argument (if there is one)''' if i >= len(sys.argv): Fatal("'%s' expected an argument" % sys.argv[i]) if sys.argv[i][:1] != '-': return True, sys.argv[i] else: return False, default ### MAIN if __name__=='__main__': verbose = 0 debug = 0 infile = "infile" outfile = "outfile" options_start = 3 # --- Parse two positional parameters --- n1 = int(PosArg(1)) n2 = int(PosArg(2)) # --- Parse an optional parameters --- present, a3 = OptArg(3,50) n3 = int(a3) options_start += int(present) # --- Parse rest of command line --- skip = 0 for i in range(options_start, len(sys.argv)): if not skip: if sys.argv[i][:2] == "-d": debug ^= 1 elif sys.argv[i][:2] == "-v": verbose ^= 1 elif sys.argv[i][:2] == "-i": (skip,infile) = NextArg(i) elif sys.argv[i][:2] == "-o": (skip,outfile) = NextArg(i) elif sys.argv[i][:2] == "-h": HelpAndExit() elif sys.argv[i][:1] == "-": Fatal("'%s' unknown argument" % sys.argv[i]) else: Fatal("'%s' unexpected" % sys.argv[i]) else: skip = 0 print("Number 1 = %d" % n1) print("Number 2 = %d" % n2) print("Number 3 = %d" % n3) print("Debug = %d" % debug) print("verbose = %d" % verbose) print("infile = %s" % infile) print("outfile = %s" % outfile) 
  • Откройте файл в Visual Studio с определенным номером строки
  • Как анализировать аргументы командной строки на C ++?
  • Тайм-аут команды в bash без лишней задержки
  • Инструмент командной строки для сброса версии Windows DLL?
  • JUnit: Как имитировать тестирование System.in?
  • Что является более быстрой альтернативой http.server (или SimpleHTTPServer) Python?
  • Замена строк в пакетном файле
  • Как выполнить загрузку и загрузку FTP?
  • отправлять / отправлять xml-файл с помощью командной строки curl
  • как показать общие линии (обратный дифференциал)?
  • Как вы запускаете .exe с параметрами с помощью оболочки vba ()?
  • Interesting Posts

    Преобразование файлов MP4, AVI, MOV в коллекцию PNG, JPG или GIF кадров

    setValue: forUndefinedKey: этот class не является ключевым значением, совместимым с кодировкой для ключа

    Установка MacPorts на Snow Leopard

    Angular 2: Как вы визуализируете HTML из ответа JSON без отображения тегов пользователю?

    Неопределенное поведение sizeof (* ptr) при указании на недопустимую память?

    Как получить данные формы Redux в другом компоненте

    Использование символической ссылки в Windows XP

    Открыть адрес во внешнем приложении из браузера Chrome

    Как сопоставить вектор значений другому вектору с моей собственной пользовательской картой в R

    Возможно ли сделать расширение Array в Swift, которое ограничено одним classом?

    Вставка одной dll внутри другого в качестве встроенного ресурса, а затем вызов ее из моего кода

    Синхронизация контактов между Mac, Nokia E51 и iPod touch

    Разница в производительности между MSVC и GCC для высоко оптимизированного матричного кода

    javac для компиляции всех java-файлов в данной директории рекурсивно

    Создание именованных труб C ++ Windows

    Давайте будем гением компьютера.