optparse — анализатор параметров командной строки
Исходный код: Lib/optparse.py
Выбор библиотеки для разбора аргументов
Стандартная библиотека включает три библиотеки для разбора аргументов:
-
getopt: модуль, близко повторяющий процедурный API Cgetopt. Включён в стандартную библиотеку ещё до первоначального выпуска Python 1.0. -
optparse: декларативная заменаgetopt, предоставляющая эквивалентные возможности без необходимости реализовывать логику процедурного разбора параметров отдельно в каждом приложении. Включена в стандартную библиотеку начиная с выпуска Python 2.3. -
argparse: более категоричная альтернативаoptparse, по умолчанию предоставляющая больше возможностей за счёт меньшей гибкости приложений в управлении точным способом обработки аргументов. Включена в стандартную библиотеку начиная с выпусков Python 2.7 и Python 3.2.
Если нет особых ограничений на проектирование разбора аргументов, для реализации приложений командной строки рекомендуется использовать argparse, поскольку она предоставляет наиболее широкий набор базовых возможностей при минимальном объёме кода на уровне приложения.
getopt сохраняется почти исключительно ради обратной совместимости. Однако у него есть и узкая область применения: прототипирование и тестирование обработки аргументов командной строки в приложениях на C, основанных на getopt.
Следует рассматривать optparse как альтернативу argparse в следующих случаях:
- приложение уже использует
optparse, и разработчики не хотят рисковать столкнуться с тонкими изменениями поведения, которые могут возникнуть при переходе наargparse - приложению требуется дополнительный контроль над тем, как параметры и позиционные аргументы чередуются в командной строке (включая возможность полностью отключить чередование)
- приложению требуется дополнительный контроль над пошаговым разбором элементов командной строки (хотя
argparseподдерживает эту возможность, точный способ её практической работы нежелателен в некоторых случаях) - приложению требуется дополнительный контроль над обработкой параметров, принимающих значения, которые могут начинаться с
-(например, делегированных параметров, передаваемых запускаемым подпроцессам) - приложению требуется какое-либо другое поведение при обработке параметров командной строки, которое не поддерживается в
argparse, но может быть реализовано с помощью низкоуровневого интерфейса, предоставляемогоoptparse
По этим причинам optparse, вероятно, станет лучшей основой для авторов библиотек, разрабатывающих сторонние библиотеки обработки аргументов командной строки.
В качестве конкретного примера рассмотрим две следующие конфигурации разбора аргументов командной строки: первая использует optparse, вторая — argparse:
import optparse
if __name__ == '__main__':
parser = optparse.OptionParser()
parser.add_option('-o', '--output')
parser.add_option('-v', dest='verbose', action='store_true')
opts, args = parser.parse_args()
process(args, output=opts.output, verbose=opts.verbose)
import argparse
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-o', '--output')
parser.add_argument('-v', dest='verbose', action='store_true')
parser.add_argument('rest', nargs='*')
args = parser.parse_args()
process(args.rest, output=args.output, verbose=args.verbose)
Наиболее очевидное различие состоит в том, что в варианте optparse приложение обрабатывает аргументы, не являющиеся параметрами, отдельно, после завершения обработки параметров. В варианте argparse позиционные аргументы объявляются и обрабатываются так же, как именованные параметры.
Однако вариант argparse также обрабатывает некоторые сочетания параметров иначе, чем вариант optparse. Например (помимо прочих различий):
- при передаче
-o -vв случае использованияoptparseполучаютсяoutput="-v"иverbose=False, а в случаеargparseвозникает ошибка использования (с сообщением, что для-o/--outputне задано значение, поскольку-vинтерпретируется как флаг подробного вывода) - аналогично, при передаче
-o --в случае использованияoptparseполучаютсяoutput="--"иargs=(), а в случаеargparseвозникает ошибка использования (также с сообщением, что для-o/--outputне задано значение, поскольку--интерпретируется как признак завершения обработки параметров, после которого все оставшиеся значения считаются позиционными аргументами) - при передаче
-o=fooв случае использованияoptparseполучаетсяoutput="=foo", а в случаеargparse—output="foo"(поскольку=обрабатывается особым образом как альтернативный разделитель значений параметров)
Являются ли эти различия в поведении варианта argparse преимуществом или проблемой, зависит от конкретного сценария использования приложения командной строки.
См. также
click — сторонняя библиотека для обработки аргументов (изначально основанная на optparse), которая позволяет создавать приложения командной строки в виде набора декорированных функций реализации команд.
Другие сторонние библиотеки, такие как typer или msgspec-click, позволяют задавать интерфейсы командной строки таким образом, чтобы эффективнее интегрировать их со статической проверкой аннотаций типов Python.
Введение
optparse — это более удобная, гибкая и мощная библиотека для разбора параметров командной строки, чем минималистичный модуль getopt. В optparse используется более декларативный стиль разбора командной строки: вы создаёте экземпляр OptionParser, добавляете в него параметры и разбираете командную строку. optparse позволяет пользователям задавать параметры в традиционном синтаксисе GNU/POSIX, а также автоматически генерирует сообщения об использовании и справке.
Вот пример использования optparse в простом скрипте:
from optparse import OptionParser
...
parser = OptionParser()
parser.add_option("-f", "--file", dest="filename",
help="write report to FILE", metavar="FILE")
parser.add_option("-q", "--quiet",
action="store_false", dest="verbose", default=True,
help="don't print status messages to stdout")
(options, args) = parser.parse_args()
Теперь с помощью этих нескольких строк кода пользователи вашего скрипта могут выполнять в командной строке привычные действия, например:
<yourscript> --file=outfile -q
При разборе командной строки optparse задаёт атрибуты объекта options, возвращаемого parse_args(), на основе значений, заданных пользователем в командной строке. После того как parse_args() завершит разбор этой командной строки, options.filename будет равно "outfile", а options.verbose — False. optparse поддерживает короткие и длинные параметры, позволяет объединять короткие параметры и связывать параметры с аргументами различными способами. Поэтому следующие командные строки эквивалентны приведённому выше примеру:
<yourscript> -f outfile --quiet <yourscript> --quiet --file outfile <yourscript> -q -foutfile <yourscript> -qfoutfile
Кроме того, пользователи могут выполнить одну из следующих команд
<yourscript> -h <yourscript> --help
и optparse выведет краткую сводку параметров вашего скрипта:
Usage: <yourscript> [options] Options: -h, --help show this help message and exit -f FILE, --file=FILE write report to FILE -q, --quiet don't print status messages to stdout
где значение yourscript определяется во время выполнения (обычно из sys.argv[0]).
Общие сведения
optparse изначально была разработана для поощрения создания программ с понятными интерфейсами командной строки, которые следуют соглашениям, установленным семейством функций getopt(), доступных разработчикам на C. Поэтому библиотека поддерживает только наиболее распространённый синтаксис и семантику командной строки, традиционно используемые в Unix. Если вы не знакомы с этими соглашениями, прочитайте этот раздел, чтобы ознакомиться с ними.
Терминология
- аргумент
-
строка, введённая в командной строке и переданная оболочкой в
execl()илиexecv(). В Python аргументы являются элементамиsys.argv[1:](sys.argv[0]— имя выполняемой программы). В оболочках Unix также используется термин «слово».Иногда бывает полезно заменить список аргументов на список, отличный от
sys.argv[1:], поэтому под «аргументом» следует понимать «элементsys.argv[1:]или другого списка, предоставленного вместоsys.argv[1:]». - параметр
-
аргумент, используемый для передачи дополнительной информации, которая помогает управлять выполнением программы или настраивать его. Существует множество синтаксисов параметров; традиционный синтаксис Unix — дефис («-») и одна буква, например
-xили-F. Кроме того, традиционный синтаксис Unix позволяет объединять несколько параметров в один аргумент: например,-x -Fэквивалентно-xF. Проект GNU ввёл--, за которым следует несколько слов, разделённых дефисами, например--fileили--dry-run. Это единственные два синтаксиса параметров, поддерживаемыеoptparse.Встречаются и другие синтаксисы параметров, например:
- дефис, за которым следуют несколько букв, например
-pf(это не то же самое, что несколько параметров, объединённых в один аргумент) - дефис, за которым следует целое слово, например
-file(технически это эквивалентно предыдущему синтаксису, но обычно они не встречаются в одной программе) - знак плюс, за которым следует одна буква, несколько букв или слово, например
+f,+rgb - косая черта, за которой следует одна буква, несколько букв или слово, например
/f,/file
Эти синтаксисы параметров не поддерживаются
optparseи никогда поддерживаться не будут. Это сделано намеренно: первые три не являются стандартными ни в одной среде, а последний имеет смысл, только если вы разрабатываете программу исключительно для Windows или некоторых устаревших платформ (например, VMS, MS-DOS). - дефис, за которым следуют несколько букв, например
- аргумент параметра
-
аргумент, следующий за параметром, тесно связанный с ним и удаляемый из списка аргументов при обработке этого параметра. В
optparseаргументы параметров могут передаваться отдельно от параметра:-f foo --file foo
или включаться в тот же аргумент:
-ffoo --file=foo
Как правило, данный параметр либо принимает аргумент, либо не принимает его. Многие хотят, чтобы существовала возможность задавать «необязательные аргументы параметров», то есть чтобы некоторые параметры принимали аргумент, если он указан, и не принимали его, если он отсутствует. Эта возможность вызывает споры, поскольку делает разбор неоднозначным: если
-aпринимает необязательный аргумент, а-b— отдельный параметр, как интерпретировать-ab? Из-за этой неоднозначностиoptparseне поддерживает такую возможность. - позиционный аргумент
-
элемент, оставшийся в списке аргументов после разбора параметров, то есть после разбора параметров и их аргументов и удаления их из списка.
- обязательный параметр
-
параметр, который необходимо указать в командной строке; обратите внимание, что выражение «обязательный параметр» противоречиво по смыслу.
optparseне мешает реализовать обязательные параметры, но и не особенно помогает в этом.
Например, рассмотрим следующую гипотетическую командную строку:
prog -v --report report.txt foo bar
И -v, и --report — параметры. Предположим, что --report принимает один аргумент; тогда report.txt — аргумент параметра. foo и bar — позиционные аргументы.
Для чего нужны параметры?
Параметры используются для передачи дополнительной информации, позволяющей настраивать выполнение программы. Если это было неясно, параметры обычно являются необязательными. Программа должна нормально запускаться вообще без параметров. (Выберите наугад программу из набора утилит Unix или GNU. Может ли она работать без каких-либо параметров и при этом оставаться полезной? Основные исключения — find, tar и dd — все они представляют собой странные исключения, которые справедливо критиковали за нестандартный синтаксис и запутанные интерфейсы.)
Многие хотят, чтобы в их программах были «обязательные параметры». Подумайте об этом. Если параметр обязателен, значит, он необязательным не является! Если программе абсолютно необходима какая-либо информация для успешного запуска, для этого и нужны позиционные аргументы.
В качестве примера удачного проектирования интерфейса командной строки рассмотрим скромную утилиту cp для копирования файлов. Пытаться копировать файлы без указания места назначения и хотя бы одного исходного файла не имеет смысла. Поэтому cp завершится с ошибкой, если запустить её без аргументов. При этом у неё гибкий и удобный синтаксис, для которого не нужны параметры:
cp SOURCE DEST cp SOURCE ... DEST-DIR
Этого вполне достаточно для многих задач. Большинство реализаций cp предоставляют целый ряд параметров, позволяющих точно настроить копирование файлов: сохранять права доступа и время изменения, не переходить по символическим ссылкам, запрашивать подтверждение перед перезаписью существующих файлов и т. д. Но ничто из этого не отвлекает от главной задачи cp — копировать один файл в другой либо несколько файлов в другой каталог.
Для чего нужны позиционные аргументы?
Позиционные аргументы предназначены для передачи той информации, без которой программа совершенно точно не сможет работать.
В хорошем пользовательском интерфейсе должно быть как можно меньше обязательных требований. Если для успешного запуска программы требуется 17 отдельных элементов информации, не так уж важно, как именно вы получите их от пользователя: большинство людей сдадутся и откажутся от программы, прежде чем им удастся её запустить. Это справедливо независимо от типа интерфейса — командная строка, файл конфигурации или графический интерфейс: если предъявлять пользователям так много требований, большинство из них просто откажутся от программы.
Короче говоря, постарайтесь свести к минимуму объём информации, которую пользователи обязаны предоставить, — по возможности используйте разумные значения по умолчанию. Разумеется, программы также должны быть достаточно гибкими. Для этого и нужны параметры. Неважно, являются ли они записями в файле конфигурации, элементами управления в диалоговом окне «Настройки» графического интерфейса или параметрами командной строки: чем больше параметров вы реализуете, тем гибче становится программа и тем сложнее её реализация. У чрезмерной гибкости тоже есть недостатки: слишком большое количество параметров может перегрузить пользователей и значительно усложнить сопровождение кода.
Учебное руководство
Хотя optparse довольно гибок и мощен, в большинстве случаев им также легко пользоваться. В этом разделе рассматриваются шаблоны кода, общие для всех программ на основе optparse.
Сначала нужно импортировать класс OptionParser; затем в начале основной программы создать экземпляр OptionParser:
from optparse import OptionParser ... parser = OptionParser()
Теперь можно приступить к определению параметров. Базовый синтаксис таков:
parser.add_option(opt_str, ...,
attr=value, ...)
У каждого параметра есть одна или несколько строк параметра, например -f или --file, а также несколько атрибутов, указывающих optparse, чего ожидать и что делать при обнаружении этого параметра в командной строке.
Как правило, у каждого параметра есть одна короткая и одна длинная строка параметра, например:
parser.add_option("-f", "--file", ...)
Можно определить любое количество коротких и длинных строк параметра (в том числе ни одной), если в итоге есть хотя бы одна строка параметра.
Строки параметров, передаваемые в OptionParser.add_option(), фактически служат метками параметра, определяемого этим вызовом. Для краткости мы часто будем говорить об обнаружении параметра в командной строке; на самом деле optparse обнаруживает строки параметров и по ним находит соответствующие параметры.
Определив все параметры, укажите optparse разобрать командную строку программы:
(options, args) = parser.parse_args()
(При желании можно передать пользовательский список аргументов в parse_args(), но это редко требуется: по умолчанию используется sys.argv[1:].)
parse_args() возвращает два значения:
-
options— объект, содержащий значения всех параметров. Например, если--fileпринимает один строковый аргумент, тоoptions.fileбудет именем файла, указанным пользователем, илиNone, если пользователь не указал этот параметр -
args— список позиционных аргументов, оставшихся после разбора параметров
В этом разделе учебного руководства рассматриваются только четыре наиболее важных атрибута параметров: action, type, dest (назначение) и help. Из них action — самый важный.
Понимание действий параметров
Действия указывают optparse, что делать при обнаружении параметра в командной строке. В optparse задан фиксированный набор действий; добавление новых действий — продвинутая тема, рассматриваемая в разделе Расширение optparse. Большинство действий предписывают optparse сохранить значение в какой-либо переменной — например, взять строку из командной строки и сохранить её в атрибуте options.
Если действие параметра не указано, optparse по умолчанию использует store.
Действие store
Самое распространённое действие параметра — store. Оно предписывает optparse взять следующий аргумент (или оставшуюся часть текущего аргумента), проверить, что он имеет правильный тип, и сохранить его в выбранном вами месте назначения.
Например:
parser.add_option("-f", "--file",
action="store", type="string", dest="filename")
Теперь создадим фиктивную командную строку и попросим optparse разобрать её:
args = ["-f", "foo.txt"] (options, args) = parser.parse_args(args)
Когда optparse встречает строку параметра -f, оно использует следующий аргумент, foo.txt, и сохраняет его в options.filename. Поэтому после вызова parse_args() значение options.filename равно "foo.txt".
Среди других типов параметров, поддерживаемых optparse, — int и float. Вот параметр, ожидающий целочисленный аргумент:
parser.add_option("-n", type="int", dest="num")
Обратите внимание: у этого параметра нет длинной строки, что вполне допустимо. Также действие не указано явно, поскольку по умолчанию используется store.
Разберём ещё одну фиктивную командную строку. На этот раз укажем аргумент параметра сразу после самого параметра: поскольку -n42 (один аргумент) эквивалентно -n 42 (два аргумента), код
(options, args) = parser.parse_args(["-n42"]) print(options.num)
выведет 42.
Если тип не указан, optparse предполагает string. Учитывая, что действием по умолчанию является store, первый пример можно значительно сократить:
parser.add_option("-f", "--file", dest="filename")
Если место назначения не указано, optparse выбирает подходящее значение по умолчанию на основе строк параметра: если первая длинная строка параметра — --foo-bar, то местом назначения по умолчанию будет foo_bar. Если длинных строк параметра нет, optparse проверяет первую короткую строку параметра: место назначения по умолчанию для -f — f.
optparse также включает встроенный тип complex. Добавление типов рассматривается в разделе Расширение optparse.
Обработка логических параметров-флагов
Параметры-флаги, которые устанавливают переменную в значение true или false при обнаружении определённого параметра, встречаются довольно часто. optparse поддерживает их с помощью двух отдельных действий: store_true и store_false. Например, можно создать флаг verbose, который включается с помощью -v и выключается с помощью -q:
parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose")
Здесь у нас есть два разных параметра с одним и тем же местом назначения, что вполне допустимо. (Это лишь означает, что при задании значений по умолчанию нужно быть немного внимательнее — см. ниже.)
Когда optparse встречает в командной строке -v, оно устанавливает options.verbose в значение True; когда оно встречает -q, значение options.verbose устанавливается в False.
Другие действия
Среди других действий, поддерживаемых optparse:
-
"store_const" -
сохранить постоянное значение, предварительно заданное с помощью
Option.const -
"append" -
добавить аргумент этого параметра в список
-
"count" -
увеличить счётчик на единицу
-
"callback" -
вызвать указанную функцию
Эти действия рассматриваются в разделах Справочное руководство и Обратные вызовы параметров.
Значения по умолчанию
Во всех приведённых выше примерах при обнаружении определённых параметров командной строки задаётся значение некоторой переменной («места назначения»). Что произойдёт, если эти параметры не встретятся? Поскольку мы не указали значения по умолчанию, все они будут равны None. Обычно этого достаточно, но иногда требуется более гибкое управление. optparse позволяет указать значение по умолчанию для каждого места назначения; оно присваивается до разбора командной строки.
Сначала рассмотрим пример с verbose/quiet. Если мы хотим, чтобы optparse присваивал verbose значение True, если не указан -q, можно сделать так:
parser.add_option("-v", action="store_true", dest="verbose", default=True)
parser.add_option("-q", action="store_false", dest="verbose")
Поскольку значения по умолчанию относятся к месту назначения, а не к какому-либо конкретному параметру, и у этих двух параметров одно и то же место назначения, следующий вариант полностью эквивалентен:
parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose", default=True)
Рассмотрим такой пример:
parser.add_option("-v", action="store_true", dest="verbose", default=False)
parser.add_option("-q", action="store_false", dest="verbose", default=True)
И снова значением по умолчанию для verbose будет True: учитывается последнее значение по умолчанию, заданное для данного места назначения.
Более понятный способ указать значения по умолчанию — метод set_defaults() класса OptionParser, который можно вызвать в любой момент до вызова parse_args():
parser.set_defaults(verbose=True) parser.add_option(...) (options, args) = parser.parse_args()
Как и прежде, для заданного места назначения учитывается последнее указанное значение. Для ясности старайтесь использовать только один из двух способов задания значений по умолчанию.
Формирование справки
Возможность optparse автоматически формировать текст справки и инструкции по использованию полезна при создании удобных интерфейсов командной строки. Достаточно задать значение help для каждого параметра и, при желании, краткое сообщение об использовании для всей программы. Вот OptionParser, которому переданы понятные пользователю (документированные) параметры:
usage = "usage: %prog [options] arg1 arg2"
parser = OptionParser(usage=usage)
parser.add_option("-v", "--verbose",
action="store_true", dest="verbose", default=True,
help="make lots of noise [default]")
parser.add_option("-q", "--quiet",
action="store_false", dest="verbose",
help="be vewwy quiet (I'm hunting wabbits)")
parser.add_option("-f", "--filename",
metavar="FILE", help="write output to FILE")
parser.add_option("-m", "--mode",
default="intermediate",
help="interaction mode: novice, intermediate, "
"or expert [default: %default]")
Если optparse встретит в командной строке -h или --help либо если просто вызвать parser.print_help(), оно выведет в стандартный поток вывода следующее:
Usage: <yourscript> [options] arg1 arg2
Options:
-h, --help show this help message and exit
-v, --verbose make lots of noise [default]
-q, --quiet be vewwy quiet (I'm hunting wabbits)
-f FILE, --filename=FILE
write output to FILE
-m MODE, --mode=MODE interaction mode: novice, intermediate, or
expert [default: intermediate]
(Если вывод справки вызван параметром справки, optparse завершает работу после вывода текста справки.)
Здесь многое сделано для того, чтобы optparse сформировал наилучшее сообщение справки:
-
скрипт задаёт собственное сообщение об использовании:
usage = "usage: %prog [options] arg1 arg2"
optparseподставляет в строку использования имя текущей программы вместо%prog, то естьos.path.basename(sys.argv[0]). Полученная строка выводится перед подробной справкой по параметрам.Если строка использования не задана,
optparseиспользует простой, но разумный вариант по умолчанию:"Usage: %prog [options]". Он подходит, если скрипт не принимает позиционные аргументы. - для каждого параметра задана строка справки, и не нужно беспокоиться о переносе строк —
optparseсам переносит строки и форматирует справку. -
в автоматически сформированной справке для параметров, принимающих значение, указывается этот факт, например для параметра «mode»:
-m MODE, --mode=MODE
Здесь «MODE» называется метапеременной: она обозначает аргумент, который пользователь должен передать в
-m/--mode. По умолчаниюoptparseпреобразует имя переменной назначения в верхний регистр и использует его как метапеременную. Иногда это нежелательно — например, параметр--filenameявно задаётmetavar="FILE", в результате чего автоматически сформированное описание параметра выглядит так:-f FILE, --filename=FILE
Это важно не только для экономии места: в написанном вручную тексте справки метапеременная
FILEпомогает пользователю понять связь между полуформальным синтаксисом-f FILEи неформальным описанием «записать вывод в FILE». Это простой, но эффективный способ сделать справку гораздо яснее и полезнее для конечных пользователей. - если у параметра есть значение по умолчанию, в строке справки можно указать
%default—optparseзаменит его наstr()значения параметра по умолчанию. Если у параметра нет значения по умолчанию (или его значение равноNone),%defaultзаменяется наnone.
Группировка параметров
При работе с большим количеством параметров удобно группировать их, чтобы улучшить вывод справки. OptionParser может содержать несколько групп параметров, каждая из которых может содержать несколько параметров.
Группа параметров создаётся с помощью класса OptionGroup:
-
class optparse.OptionGroup(parser, title, description=None) -
где
- parser — экземпляр
OptionParser, в который будет добавлена группа - title — заголовок группы
- description — необязательное подробное описание группы
- parser — экземпляр
OptionGroup наследуется от OptionContainer (как и OptionParser), поэтому для добавления параметра в группу можно использовать метод add_option().
После объявления всех параметров группа добавляется в ранее созданный анализатор с помощью метода OptionParser add_option_group().
Продолжая пример из предыдущего раздела, добавить в анализатор OptionGroup просто:
group = OptionGroup(parser, "Dangerous Options",
"Caution: use these options at your own risk. "
"It is believed that some of them bite.")
group.add_option("-g", action="store_true", help="Group option.")
parser.add_option_group(group)
В результате будет выведена следующая справка:
Usage: <yourscript> [options] arg1 arg2
Options:
-h, --help show this help message and exit
-v, --verbose make lots of noise [default]
-q, --quiet be vewwy quiet (I'm hunting wabbits)
-f FILE, --filename=FILE
write output to FILE
-m MODE, --mode=MODE interaction mode: novice, intermediate, or
expert [default: intermediate]
Dangerous Options:
Caution: use these options at your own risk. It is believed that some
of them bite.
-g Group option.
Более полный пример может включать несколько групп; продолжим предыдущий пример:
group = OptionGroup(parser, "Dangerous Options",
"Caution: use these options at your own risk. "
"It is believed that some of them bite.")
group.add_option("-g", action="store_true", help="Group option.")
parser.add_option_group(group)
group = OptionGroup(parser, "Debug Options")
group.add_option("-d", "--debug", action="store_true",
help="Print debug information")
group.add_option("-s", "--sql", action="store_true",
help="Print all SQL statements executed")
group.add_option("-e", action="store_true", help="Print every action done")
parser.add_option_group(group)
в результате будет получен следующий вывод:
Usage: <yourscript> [options] arg1 arg2
Options:
-h, --help show this help message and exit
-v, --verbose make lots of noise [default]
-q, --quiet be vewwy quiet (I'm hunting wabbits)
-f FILE, --filename=FILE
write output to FILE
-m MODE, --mode=MODE interaction mode: novice, intermediate, or expert
[default: intermediate]
Dangerous Options:
Caution: use these options at your own risk. It is believed that some
of them bite.
-g Group option.
Debug Options:
-d, --debug Print debug information
-s, --sql Print all SQL statements executed
-e Print every action done
Ещё один полезный метод, особенно при программной работе с группами параметров:
-
OptionParser.get_option_group(opt_str) -
Возвращает
OptionGroup, которой принадлежит короткая или длинная строка параметра opt_str (например,'-o'или'--option'). Если такойOptionGroupнет, возвращаетNone.
Вывод строки версии
Подобно краткому сообщению об использовании, optparse может также выводить строку версии программы. Эту строку нужно передать в качестве аргумента version класса OptionParser:
parser = OptionParser(usage="%prog [-f] [-q]", version="%prog 1.0")
%prog раскрывается так же, как и в usage. В остальном строка version может содержать всё, что угодно. Если она задана, optparse автоматически добавляет в анализатор параметр --version. При обнаружении этого параметра в командной строке анализатор раскрывает строку version (заменяя %prog), выводит её в стандартный поток вывода и завершает работу.
Например, если ваш скрипт называется /usr/bin/foo:
$ /usr/bin/foo --version foo 1.0
Для вывода и получения строки version можно использовать следующие два метода:
-
OptionParser.print_version(file=None) -
Выводит сообщение о версии текущей программы (
self.version) в файл file (по умолчанию — стандартный поток вывода). Как и в случае сprint_usage(), все вхождения%progвself.versionзаменяются именем текущей программы. Ничего не делает, еслиself.versionпусто или не определено.
-
OptionParser.get_version() -
То же, что и
print_version(), но возвращает строку версии, а не выводит её.
Как optparse обрабатывает ошибки
Существует два основных класса ошибок, о которых optparse должно заботиться: ошибки программиста и ошибки пользователя. Ошибки программиста обычно возникают из-за некорректных вызовов OptionParser.add_option(), например недопустимых строк параметров, неизвестных или отсутствующих атрибутов параметров и т. д. Они обрабатываются обычным способом: вызывается исключение (либо optparse.OptionError, либо TypeError), и программа аварийно завершается.
Обработка ошибок пользователя гораздо важнее, поскольку они неизбежны, как бы стабильно ни работал ваш код. optparse может автоматически обнаруживать некоторые ошибки пользователя, например неверные аргументы параметров (передача -n 4x, когда -n ожидает целочисленный аргумент) и отсутствующие аргументы (-n в конце командной строки, когда -n ожидает аргумент любого типа). Кроме того, можно вызвать OptionParser.error(), чтобы сообщить об ошибке, определённой приложением:
(options, args) = parser.parse_args()
...
if options.a and options.b:
parser.error("options -a and -b are mutually exclusive")
В обоих случаях optparse обрабатывает ошибку одинаково: выводит сообщение об использовании программы и сообщение об ошибке в стандартный поток ошибок и завершает работу с кодом ошибки 2.
Рассмотрим первый пример выше, в котором пользователь передаёт 4x параметру, ожидающему целое число:
$ /usr/bin/foo -n 4x Usage: foo [options] foo: error: option -n: invalid integer value: '4x'
Или случай, когда пользователь вообще не передаёт значение:
$ /usr/bin/foo -n Usage: foo [options] foo: error: -n option requires an argument
Сообщения об ошибках, сформированные optparse, всегда содержат упоминание параметра, вызвавшего ошибку; не забывайте делать то же самое, вызывая OptionParser.error() в коде приложения.
Если поведение optparse при обработке ошибок по умолчанию вам не подходит, необходимо создать подкласс OptionParser и переопределить его методы exit() и/или error().
Объединяем всё вместе
Обычно скрипты на основе optparse выглядят так:
from optparse import OptionParser
...
def main():
usage = "usage: %prog [options] arg"
parser = OptionParser(usage)
parser.add_option("-f", "--file", dest="filename",
help="read data from FILENAME")
parser.add_option("-v", "--verbose",
action="store_true", dest="verbose")
parser.add_option("-q", "--quiet",
action="store_false", dest="verbose")
...
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error("incorrect number of arguments")
if options.verbose:
print("reading %s..." % options.filename)
...
if __name__ == "__main__":
main()
Справочное руководство
Создание анализатора
Первый шаг при использовании optparse — создание экземпляра OptionParser.
-
class optparse.OptionParser(...) -
Конструктор OptionParser не требует обязательных аргументов, но принимает ряд необязательных аргументов-ключевых слов. Их всегда следует передавать как аргументы-ключевые слова, то есть не следует полагаться на порядок объявления аргументов.
-
usage (default: "%prog [options]") -
Сводка по использованию, которую следует выводить, если программа запущена с ошибками или с параметром справки. Когда
optparseвыводит строку использования, она заменяет%progнаos.path.basename(sys.argv[0])(или наprog, если вы передали этот аргумент-ключевое слово). Чтобы подавить сообщение об использовании, передайте специальное значениеoptparse.SUPPRESS_USAGE. -
option_list (default: []) -
Список объектов Option, которыми нужно заполнить анализатор. Параметры из
option_listдобавляются после любых параметров изstandard_option_list(атрибута класса, который могут задавать подклассы OptionParser), но перед любыми параметрами версии или справки. Устарело; вместо этого после создания анализатора используйтеadd_option(). -
option_class (default: optparse.Option) -
Класс, который будет использоваться при добавлении параметров в анализатор с помощью
add_option(). -
version (default: None) -
Строка версии, выводимая, когда пользователь задаёт параметр версии. Если для
versionпередано истинное значение,optparseавтоматически добавляет параметр версии с единственной строкой параметра--version. Подстрока%progзаменяется так же, как и дляusage. -
conflict_handler (default: "error") -
Определяет, что делать при добавлении в анализатор параметров с конфликтующими строками параметров; см. раздел Конфликты между параметрами.
-
description (default: None) -
Текстовый абзац с кратким обзором программы.
optparseформатирует этот абзац с учётом текущей ширины терминала и выводит его, когда пользователь запрашивает справку (послеusage, но перед списком параметров). -
formatter (default: a new IndentedHelpFormatter) -
Экземпляр optparse.HelpFormatter, который будет использоваться для вывода текста справки.
optparseпредоставляет для этого два конкретных класса: IndentedHelpFormatter и TitledHelpFormatter. -
add_help_option (default: True) -
Если значение истинно,
optparseдобавит в анализатор параметр справки (со строками параметров-hи--help). -
prog -
Строка, используемая вместо
os.path.basename(sys.argv[0])при подстановке%progвusageиversion. -
epilog (default: None) -
Абзац текста справки, выводимый после справки по параметрам.
-
Заполнение анализатора
Есть несколько способов заполнить анализатор параметрами. Предпочтительный способ — использовать OptionParser.add_option(), как показано в разделе Учебное пособие. add_option() можно вызвать одним из двух способов:
- передать ему экземпляр Option (возвращаемый
make_option()) - передать ему любую комбинацию позиционных аргументов и аргументов-ключевых слов, допустимую для
make_option()(то есть для конструктора Option); в этом случае экземпляр Option будет создан автоматически
Другой способ — передать конструктору OptionParser список заранее созданных экземпляров Option, например:
option_list = [
make_option("-f", "--filename",
action="store", type="string", dest="filename"),
make_option("-q", "--quiet",
action="store_false", dest="verbose"),
]
parser = OptionParser(option_list=option_list)
(make_option() — фабричная функция для создания экземпляров Option; в настоящее время это псевдоним конструктора Option. В будущей версии optparse класс Option может быть разделён на несколько классов, и make_option() выберет подходящий класс для создания экземпляра. Не создавайте экземпляры Option напрямую.)
Определение параметров
Каждый экземпляр Option представляет собой набор эквивалентных строк параметров командной строки, например -f и --file. Можно указать любое количество коротких или длинных строк параметров, но необходимо указать хотя бы одну строку параметра.
Канонический способ создания экземпляра Option — использовать метод add_option() класса OptionParser.
-
OptionParser.add_option(option) - OptionParser.add_option(*opt_str, attr=value, ...)
-
Чтобы определить параметр только с короткой строкой:
parser.add_option("-f", attr=value, ...)А чтобы определить параметр только с длинной строкой:
parser.add_option("--foo", attr=value, ...)Аргументы-ключевые слова задают атрибуты нового объекта Option. Важнейший атрибут параметра —
action; он во многом определяет, какие другие атрибуты имеют значение или являются обязательными. Если передать не относящиеся к параметру атрибуты или не передать обязательные,optparseвызовет исключениеOptionErrorс объяснением ошибки.Действие параметра определяет, что делает
optparseпри встрече с этим параметром в командной строке. Стандартные действия параметров, заданные вoptparse:-
"store" -
сохранить аргумент этого параметра (по умолчанию)
-
"store_const" -
сохранить постоянное значение, заранее заданное через
Option.const -
"store_true" -
сохранить
True -
"store_false" -
сохранить
False -
"append" -
добавить аргумент этого параметра в список
-
"append_const" -
добавить в список постоянное значение, заранее заданное через
Option.const -
"count" -
увеличить счётчик на единицу
-
"callback" -
вызвать указанную функцию
-
"help" -
вывести сообщение об использовании со всеми параметрами и их описаниями
(Если действие не задано, по умолчанию используется
"store". Для этого действия также можно указать атрибуты параметраtypeиdest; см. раздел Стандартные действия параметров.) -
Как видно, большинство действий предполагают сохранение или изменение значения где-либо. optparse всегда создаёт для этого специальный объект, обычно называемый options, который является экземпляром optparse.Values.
-
class optparse.Values -
Объект, хранящий имена и значения разобранных аргументов в виде атрибутов. Обычно создаётся при вызове
OptionParser.parse_args(); его можно заменить пользовательским подклассом, переданным аргументу values методаOptionParser.parse_args()(как описано в разделе Разбор аргументов).
Аргументы параметров (и различные другие значения) сохраняются как атрибуты этого объекта в соответствии с атрибутом параметра dest (назначение).
Например, при вызове
parser.parse_args()
одним из первых действий optparse будет создание объекта options:
options = Values()
Если один из параметров этого анализатора определён следующим образом:
parser.add_option("-f", "--file", action="store", type="string", dest="filename")
и разбираемая командная строка содержит что-либо из перечисленного ниже:
-ffoo -f foo --file=foo --file foo
то optparse при встрече с этим параметром выполнит эквивалент следующего:
options.filename = "foo"
Атрибуты параметров type и dest почти так же важны, как action, но только action имеет смысл для всех параметров.
Атрибуты параметров
-
class optparse.Option -
Один аргумент командной строки с различными атрибутами, передаваемыми конструктору как аргументы-ключевые слова. Обычно создаётся с помощью
OptionParser.add_option(), а не напрямую; его можно заменить пользовательским классом, передав аргумент option_class вOptionParser.
Следующие атрибуты параметров можно передавать как аргументы-ключевые слова в OptionParser.add_option(). Если передать атрибут, не относящийся к данному параметру, или не передать обязательный атрибут, optparse вызовет исключение OptionError.
-
Option.action -
(по умолчанию:
"store")Определяет поведение
optparseпри обнаружении этого параметра в командной строке; доступные варианты описаны здесь.
-
Option.type -
(по умолчанию:
"string")Ожидаемый тип аргумента этого параметра (например,
"string"или"int"); доступные типы параметров описаны здесь.
-
Option.dest -
(по умолчанию: определяется по строкам параметров)
Если действие параметра подразумевает запись или изменение значения где-либо, этот атрибут указывает
optparse, куда его записывать:destзадаёт атрибут объектаoptions, которыйoptparseформирует при разборе командной строки.
-
Option.default -
Значение, используемое для назначения этого параметра, если параметр не встречается в командной строке. См. также
OptionParser.set_defaults().
-
Option.nargs -
(по умолчанию: 1)
Сколько аргументов типа
typeследует обработать при обнаружении этого параметра. Если значение > 1,optparseсохранит кортеж значений вdest.
-
Option.const -
Постоянное значение, сохраняемое действиями, которые сохраняют постоянное значение.
-
Option.choices -
Для параметров типа
"choice"— список строк, из которых пользователь может выбирать.
-
Option.callback -
Для параметров с действием
"callback"— вызываемый объект, который вызывается при обнаружении этого параметра. Подробные сведения об аргументах, передаваемых вызываемому объекту, см. в разделе Функции обратного вызова параметров.
-
Option.callback_args -
Option.callback_kwargs -
Дополнительные позиционные аргументы и аргументы-ключевые слова, передаваемые в
callbackпосле четырёх стандартных аргументов обратного вызова.
-
Option.help -
Текст справки, выводимый для этого параметра в списке всех доступных параметров после того, как пользователь передаст параметр
help(например,--help). Если текст справки не задан, параметр будет выведен без него. Чтобы скрыть этот параметр, используйте специальное значениеoptparse.SUPPRESS_HELP.
-
Option.metavar -
(по умолчанию: определяется по строкам параметров)
Обозначение аргумента или аргументов параметра, используемое при выводе текста справки. Пример см. в разделе Учебное пособие.
Стандартные действия параметров
Различные действия параметров имеют немного разные требования и эффекты. У большинства действий есть несколько соответствующих атрибутов параметров, которые можно задать, чтобы управлять поведением optparse; некоторые действия требуют обязательных атрибутов, которые необходимо указать для любого параметра с таким действием.
-
"store"[относящиеся атрибуты:type,dest,nargs,choices]За параметром должен следовать аргумент, который преобразуется в значение согласно
typeи сохраняется вdest. Еслиnargs> 1, из командной строки будет обработано несколько аргументов; все они преобразуются согласноtypeи сохраняются вdestкак кортеж. См. раздел Стандартные типы параметров.Если задан
choices(список или кортеж строк), по умолчанию типом будет"choice".Если
typeне задан, по умолчанию используется"string".Если
destне задан,optparseвыводит назначение из первой длинной строки параметра (например,--foo-barподразумеваетfoo_bar). Если длинных строк параметров нет,optparseвыводит назначение из первой короткой строки параметра (например,-fподразумеваетf).Пример:
parser.add_option("-f") parser.add_option("-p", type="float", nargs=3, dest="point")При разборе командной строки
-f foo.txt -p 1 -3.5 4 -fbar.txt
optparseзадастoptions.f = "foo.txt" options.point = (1.0, -3.5, 4.0) options.f = "bar.txt"
-
"store_const"[обязательный атрибут:const; относящийся атрибут:dest]Значение
constсохраняется вdest.Пример:
parser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbose") parser.add_option("-v", "--verbose", action="store_const", const=1, dest="verbose") parser.add_option("--noisy", action="store_const", const=2, dest="verbose")Если встречается
--noisy,optparseзадастoptions.verbose = 2
-
"store_true"[относящийся атрибут:dest]Частный случай
"store_const", который сохраняетTrueвdest. -
"store_false"[относящийся атрибут:dest]Подобно
"store_true", но сохраняетFalse.Пример:
parser.add_option("--clobber", action="store_true", dest="clobber") parser.add_option("--no-clobber", action="store_false", dest="clobber") -
"append"[относящиеся атрибуты:type,dest,nargs,choices]За параметром должен следовать аргумент, который добавляется в список в
dest. Если дляdestне задано значение по умолчанию, при первом обнаружении этого параметра в командной строкеoptparseавтоматически создаёт пустой список. Еслиnargs> 1, обрабатывается несколько аргументов, а кортеж длинойnargsдобавляется вdest.Значения по умолчанию для
typeиdestтакие же, как для действия"store".Пример:
parser.add_option("-t", "--tracks", action="append", type="int")Если в командной строке встречается
-t3,optparseвыполняет эквивалент следующего:options.tracks = [] options.tracks.append(int("3"))Если немного позже встречается
--tracks=4, выполняется следующее:options.tracks.append(int("4"))Действие
appendвызывает методappendдля текущего значения параметра. Это означает, что любое указанное значение по умолчанию должно иметь методappend. Кроме того, если значение по умолчанию непустое, его элементы будут присутствовать в разобранном значении параметра, а значения из командной строки будут добавлены после них:>>> parser.add_option("--files", action="append", default=['~/.mypkg/defaults']) >>> opts, args = parser.parse_args(['--files', 'overrides.mypkg']) >>> opts.files ['~/.mypkg/defaults', 'overrides.mypkg'] -
"append_const"[обязательный атрибут:const; относящийся атрибут:dest]Подобно
"store_const", но значениеconstдобавляется вdest; как и для"append", по умолчаниюdestравноNone, а при первом обнаружении параметра автоматически создаётся пустой список. -
"count"[относящийся атрибут:dest]Увеличивает на единицу целое число, хранящееся в
dest. Если значение по умолчанию не задано, перед первым увеличениемdestприсваивается ноль.Пример:
parser.add_option("-v", action="count", dest="verbosity")При первом появлении
-vв командной строкеoptparseвыполняет эквивалент следующего:options.verbosity = 0 options.verbosity += 1
При каждом последующем появлении
-vвыполняетсяoptions.verbosity += 1
-
"callback"[обязательный атрибут:callback; относящиеся атрибуты:type,nargs,callback_args,callback_kwargs]Вызывает функцию, указанную в
callback, следующим образом:func(option, opt_str, value, parser, *args, **kwargs)
Подробнее см. в разделе Функции обратного вызова параметров.
-
"help"Выводит полное сообщение справки по всем параметрам текущего анализатора параметров. Сообщение справки формируется из строки
usage, переданной конструктору OptionParser, и строкиhelp, переданной каждому параметру.Если для параметра не задана строка
help, он всё равно будет включён в сообщение справки. Чтобы полностью исключить параметр, используйте специальное значениеoptparse.SUPPRESS_HELP.optparseавтоматически добавляет параметрhelpво все объекты OptionParser, поэтому обычно создавать его вручную не нужно.Пример:
from optparse import OptionParser, SUPPRESS_HELP # usually, a help option is added automatically, but that can # be suppressed using the add_help_option argument parser = OptionParser(add_help_option=False) parser.add_option("-h", "--help", action="help") parser.add_option("-v", action="store_true", dest="verbose", help="Be moderately verbose") parser.add_option("--file", dest="filename", help="Input file to read data from") parser.add_option("--secret", help=SUPPRESS_HELP)Если
optparseобнаружит в командной строке-hили--help, он выведет в stdout примерно такое сообщение справки (при условии, чтоsys.argv[0]равно"foo.py"):Usage: foo.py [options] Options: -h, --help Show this help message and exit -v Be moderately verbose --file=FILENAME Input file to read data from
После вывода сообщения справки
optparseзавершает процесс с кодомsys.exit(0). -
"version"Выводит в stdout номер версии, переданный объекту OptionParser, и завершает работу. Номер версии форматируется и выводится методом
print_version()класса OptionParser. Обычно это действие имеет смысл только в том случае, если аргументversionпередан конструктору OptionParser. Как и параметрыhelp, параметрыversionсоздаются редко, посколькуoptparseавтоматически добавляет их при необходимости.
Стандартные типы параметров
В optparse есть пять встроенных типов параметров: "string", "int", "choice", "float" и "complex". Если нужно добавить новые типы параметров, см. раздел Расширение optparse.
Аргументы строковых параметров не проверяются и не преобразуются: текст командной строки сохраняется в назначении (или передаётся функции обратного вызова) без изменений.
Целочисленные аргументы (тип "int") разбираются следующим образом:
- если число начинается с
0x, оно разбирается как шестнадцатеричное - если число начинается с
0, оно разбирается как восьмеричное - если число начинается с
0b, оно разбирается как двоичное - в противном случае число разбирается как десятичное
Преобразование выполняется вызовом int() с соответствующим основанием (2, 8, 10 или 16). Если преобразование завершается ошибкой, то и optparse завершится ошибкой, но сообщение будет более информативным.
Аргументы параметров "float" и "complex" преобразуются напрямую с помощью float() и complex() с аналогичной обработкой ошибок.
Параметры "choice" являются подтипом параметров "string". Атрибут параметра choices (последовательность строк) задаёт набор допустимых аргументов параметра. optparse.check_choice() сравнивает переданные пользователем аргументы с этим списком и вызывает исключение OptionValueError, если указана недопустимая строка.
Разбор аргументов
Главная цель создания и заполнения OptionParser — вызов его метода parse_args().
-
OptionParser.parse_args(args=None, values=None) -
Разбирает параметры командной строки, содержащиеся в args.
Входные параметры:
-
args -
список аргументов для обработки (по умолчанию:
sys.argv[1:]) -
values -
объект
Valuesдля сохранения аргументов параметров (по умолчанию: новый экземплярValues) — если передать существующий объект, значения параметров по умолчанию в нём не будут инициализированы
Возвращаемое значение — пара
(options, args), где-
options -
тот же объект, который был передан как values, или экземпляр
optparse.Values, созданный методомoptparse -
args -
оставшиеся позиционные аргументы после обработки всех параметров
-
Обычно оба именованных аргумента не указывают. Если передать values, он будет изменён повторными вызовами setattr() (примерно по одному на каждый аргумент параметра, сохранённый в целевом атрибуте параметра) и возвращён методом parse_args().
Если parse_args() обнаруживает ошибки в списке аргументов, он вызывает метод OptionParser error() с подходящим сообщением об ошибке для конечного пользователя. В итоге выполнение процесса завершается с кодом возврата 2 (традиционный код завершения Unix для ошибок командной строки).
Запрос и изменение анализатора параметров
Поведение анализатора параметров по умолчанию можно немного настроить; также можно изучить анализатор и посмотреть, что в нём содержится. В OptionParser предусмотрено несколько полезных методов:
-
OptionParser.disable_interspersed_args() -
Останавливает разбор при первом аргументе, не являющемся параметром. Например, если
-aи-b— простые параметры, не принимающие аргументов,optparseобычно принимает следующий синтаксис:prog -a arg1 -b arg2
и интерпретирует его так же, как
prog -a -b arg1 arg2
Чтобы отключить эту возможность, вызовите
disable_interspersed_args(). Это восстанавливает традиционный синтаксис Unix, при котором разбор параметров останавливается на первом аргументе, не являющемся параметром.Используйте этот метод, если у вас есть обработчик команд, запускающий другую команду со своими параметрами, и нужно избежать их смешения. Например, у каждой команды может быть свой набор параметров.
-
OptionParser.enable_interspersed_args() -
Продолжает разбор после первого аргумента, не являющегося параметром, позволяя чередовать параметры с аргументами команды. Это поведение используется по умолчанию.
-
OptionParser.get_option(opt_str) -
Возвращает экземпляр Option для строки параметра opt_str или
None, если ни один параметр не имеет такую строку.
-
OptionParser.has_option(opt_str) -
Возвращает
True, если OptionParser содержит параметр со строкой opt_str (например,-qили--verbose).
-
OptionParser.remove_option(opt_str) -
Если
OptionParserсодержит параметр, соответствующий opt_str, этот параметр удаляется. Если у него были другие строки параметров, все они становятся недопустимыми. Если opt_str не встречается ни у одного параметра этогоOptionParser, возникает исключениеValueError.
Конфликты между параметрами
Если не быть внимательным, легко определить параметры с конфликтующими строками:
parser.add_option("-n", "--dry-run", ...)
...
parser.add_option("-n", "--noisy", ...)
(Особенно часто это происходит, если вы создали собственный подкласс OptionParser со стандартными параметрами.)
При каждом добавлении параметра optparse проверяет, нет ли конфликтов с существующими параметрами. Если конфликты обнаружены, вызывается текущий механизм обработки конфликтов. Его можно задать в конструкторе:
parser = OptionParser(..., conflict_handler=handler)
или отдельным вызовом:
parser.set_conflict_handler(handler)
Доступны следующие обработчики конфликтов:
-
"error" (default) -
считать конфликт параметров ошибкой программирования и вызвать исключение
OptionConflictError -
"resolve" -
интеллектуально разрешать конфликты параметров (см. ниже)
В качестве примера создадим OptionParser, который интеллектуально разрешает конфликты, и добавим в него конфликтующие параметры:
parser = OptionParser(conflict_handler="resolve")
parser.add_option("-n", "--dry-run", ..., help="do no harm")
parser.add_option("-n", "--noisy", ..., help="be noisy")
На этом этапе optparse обнаруживает, что ранее добавленный параметр уже использует строку -n. Поскольку conflict_handler имеет значение "resolve", конфликт разрешается удалением -n из списка строк параметров более раннего параметра. Теперь пользователь может активировать этот параметр только с помощью --dry-run. Если пользователь запросит справку, в сообщении будет отражено это изменение:
Options: --dry-run do no harm ... -n, --noisy be noisy
Можно удалить все строки параметров ранее добавленного параметра, в результате чего у пользователя не останется возможности вызвать его из командной строки. В таком случае optparse полностью удаляет этот параметр, поэтому он не отображается в справке и где-либо ещё. Продолжим работу с уже созданным OptionParser:
parser.add_option("--dry-run", ..., help="new dry-run option")
На этом этапе исходный параметр -n/--dry-run становится недоступным, поэтому optparse удаляет его. В результате справка выглядит так:
Options: ... -n, --noisy be noisy --dry-run new dry-run option
Очистка
Экземпляры OptionParser содержат несколько циклических ссылок. Сборщик мусора Python должен справиться с ними, но при необходимости можно явно разорвать циклические ссылки, вызвав destroy() для OptionParser после завершения работы с ним. Это особенно полезно в долго работающих приложениях, где с OptionParser связаны большие графы объектов.
Другие методы
В OptionParser есть несколько других общедоступных методов:
-
OptionParser.set_usage(usage) -
Задаёт строку использования согласно правилам, описанным выше для именованного аргумента конструктора
usage. ПередачаNoneзадаёт строку использования по умолчанию; используйтеoptparse.SUPPRESS_USAGE, чтобы отключить вывод сообщения об использовании.
-
OptionParser.print_usage(file=None) -
Выводит сообщение об использовании для текущей программы (
self.usage) в file (по умолчанию — stdout). Каждое вхождение строки%progвself.usageзаменяется именем текущей программы. Ничего не делает, еслиself.usageпуст или не задан.
-
OptionParser.get_usage() -
Работает так же, как
print_usage(), но возвращает строку использования, а не выводит её.
-
OptionParser.set_defaults(dest=value, ...) -
Одновременно задаёт значения по умолчанию для нескольких целевых атрибутов параметров. Предпочтительный способ задания значений по умолчанию для параметров —
set_defaults(), поскольку несколько параметров могут иметь один и тот же целевой атрибут. Например, если несколько параметров «mode» задают один целевой атрибут, значение по умолчанию может установить любой из них, и будет использовано последнее:parser.add_option("--advanced", action="store_const", dest="mode", const="advanced", default="novice") # overridden below parser.add_option("--novice", action="store_const", dest="mode", const="novice", default="advanced") # overrides above settingЧтобы избежать этой путаницы, используйте
set_defaults():parser.set_defaults(mode="advanced") parser.add_option("--advanced", action="store_const", dest="mode", const="advanced") parser.add_option("--novice", action="store_const", dest="mode", const="novice")
Обратные вызовы параметров
Если встроенных действий и типов optparse недостаточно для ваших задач, есть два варианта: расширить optparse или определить параметр с обратным вызовом. Расширение optparse — более универсальный подход, но для многих простых случаев он избыточен. Часто достаточно простого обратного вызова.
Определение параметра с обратным вызовом состоит из двух этапов:
- определить сам параметр, используя действие
"callback" - написать обратный вызов — функцию (или метод), принимающую как минимум четыре аргумента, как описано ниже
Определение параметра с обратным вызовом
Как всегда, проще всего определить параметр с обратным вызовом с помощью метода OptionParser.add_option(). Помимо action, необходимо указать только один атрибут параметра — callback, функцию для вызова:
parser.add_option("-c", action="callback", callback=my_callback)
callback — это функция (или другой вызываемый объект), поэтому к моменту создания параметра с обратным вызовом my_callback() уже должна быть определена. В этом простом случае optparse даже не знает, принимает ли -c какие-либо аргументы, что обычно означает, что параметр аргументов не принимает: достаточно самого факта наличия -c в командной строке. Однако в некоторых случаях обратному вызову может потребоваться обрабатывать произвольное количество аргументов командной строки. Именно здесь написание обратных вызовов становится сложнее; это рассмотрено далее в этом разделе.
optparse всегда передаёт обратному вызову четыре определённых аргумента и передаёт дополнительные аргументы только в том случае, если вы укажете их с помощью callback_args и callback_kwargs. Таким образом, минимальная сигнатура функции обратного вызова выглядит так:
def my_callback(option, opt, value, parser):
Четыре аргумента обратного вызова описаны ниже.
При определении параметра с обратным вызовом можно указать и несколько других атрибутов:
-
type -
имеет обычное значение: как и для действий
"store"или"append", он указываетoptparseобработать один аргумент и преобразовать его в типtype. Однако вместо сохранения преобразованных значений где-либоoptparseпередаёт их вашей функции обратного вызова. -
nargs -
также имеет обычное значение: если этот атрибут задан и его значение > 1,
optparseобработает аргументы в количествеnargs, каждый из которых должен преобразовываться в типtype. Затем в обратный вызов передаётся кортеж преобразованных значений. -
callback_args -
кортеж дополнительных позиционных аргументов, передаваемых обратному вызову
-
callback_kwargs -
словарь дополнительных именованных аргументов, передаваемых обратному вызову
Вызов обратных вызовов
Все обратные вызовы вызываются следующим образом:
func(option, opt_str, value, parser, *args, **kwargs)
где
-
option -
экземпляр Option, вызывающий обратный вызов
-
opt_str -
строка параметра из командной строки, вызвавшая обратный вызов. (Если использовался сокращённый длинный параметр,
opt_strбудет полной канонической строкой параметра. Например, если пользователь укажет в командной строке--fooкак сокращение для--foobar, тоopt_strбудет равно"--foobar".) -
value -
аргумент этого параметра из командной строки.
optparseожидает аргумент только в том случае, если заданtype; типvalueбудет соответствовать типу, заданному для параметра. Если для этого параметраtypeравноNone(аргумент не ожидается), тоvalueбудет равноNone. Еслиnargs> 1,valueбудет кортежем значений соответствующего типа. -
parser -
экземпляр OptionParser, управляющий всем процессом. Он полезен главным образом тем, что через его атрибуты экземпляра доступны другие интересные данные:
-
parser.largs -
текущий список оставшихся аргументов — аргументов, которые были обработаны, но не являются ни параметрами, ни аргументами параметров. Список
parser.largsможно изменять, например добавлять в него аргументы. (Этот список станетargs— вторым возвращаемым значениемparse_args().) -
parser.rargs -
текущий список оставшихся аргументов: из него удалены
opt_strиvalue(если применимо), и в нём остались только аргументы, следующие за ними. Списокparser.rargsможно изменять, например обрабатывая дополнительные аргументы. -
parser.values -
объект, в котором по умолчанию хранятся значения параметров (экземпляр optparse.OptionValues). Благодаря этому обратные вызовы могут использовать тот же механизм хранения значений параметров, что и остальная часть
optparse; не нужно обращаться к глобальным переменным или замыканиям. Также можно получать или изменять значения любых параметров, уже встреченных в командной строке.
-
-
args -
кортеж произвольных позиционных аргументов, переданных через атрибут параметра
callback_args. -
kwargs -
словарь произвольных именованных аргументов, переданных через
callback_kwargs.
Возникновение ошибок в обратном вызове
Если возникли проблемы с параметром или его аргументами, функция обратного вызова должна вызвать исключение OptionValueError. optparse перехватывает его и завершает программу, выводя переданное сообщение об ошибке в stderr. Сообщение должно быть ясным, кратким и точным, а также указывать проблемный параметр. Иначе пользователю будет трудно понять, что он сделал не так.
Пример обратного вызова 1: простой обратный вызов
Вот пример параметра с обратным вызовом, который не принимает аргументов и просто отмечает, что параметр встретился:
def record_foo_seen(option, opt_str, value, parser):
parser.values.saw_foo = True
parser.add_option("--foo", action="callback", callback=record_foo_seen)
Разумеется, это можно сделать с помощью действия "store_true".
Пример обратного вызова 2: проверка порядка параметров
Вот немного более интересный пример: отметить, что параметр -a встретился, но завершить выполнение с ошибкой, если он стоит в командной строке после -b.
def check_order(option, opt_str, value, parser):
if parser.values.b:
raise OptionValueError("can't use -a after -b")
parser.values.a = 1
...
parser.add_option("-a", action="callback", callback=check_order)
parser.add_option("-b", action="store_true", dest="b")
Пример обратного вызова 3: проверка порядка параметров (обобщённый вариант)
Чтобы использовать этот обратный вызов для нескольких похожих параметров (установить флаг, но завершить выполнение с ошибкой, если -b уже встречался), потребуется немного доработать его: нужно обобщить сообщение об ошибке и устанавливаемый флаг.
def check_order(option, opt_str, value, parser):
if parser.values.b:
raise OptionValueError("can't use %s after -b" % opt_str)
setattr(parser.values, option.dest, 1)
...
parser.add_option("-a", action="callback", callback=check_order, dest='a')
parser.add_option("-b", action="store_true", dest="b")
parser.add_option("-c", action="callback", callback=check_order, dest='c')
Пример обратного вызова 4: проверка произвольного условия
Разумеется, условие может быть любым — проверять значения уже определённых параметров необязательно. Например, если параметры нельзя использовать в полнолуние, достаточно сделать следующее:
def check_moon(option, opt_str, value, parser):
if is_moon_full():
raise OptionValueError("%s option invalid when moon is full"
% opt_str)
setattr(parser.values, option.dest, 1)
...
parser.add_option("--foo",
action="callback", callback=check_moon, dest="foo")
(Определение is_moon_full() оставлено читателю в качестве упражнения.)
Пример обратного вызова 5: фиксированное число аргументов
Всё становится немного интереснее, когда вы определяете параметры с обратным вызовом, принимающие фиксированное число аргументов. Указание аргументов для такого параметра аналогично определению параметра "store" или "append": если задать type, параметр принимает один аргумент, который должен преобразовываться в указанный тип; если дополнительно задать nargs, параметр принимает nargs аргументов.
Вот пример, который просто имитирует стандартное действие "store":
def store_value(option, opt_str, value, parser):
setattr(parser.values, option.dest, value)
...
parser.add_option("--foo",
action="callback", callback=store_value,
type="int", nargs=3, dest="foo")
Обратите внимание: optparse самостоятельно обрабатывает 3 аргумента и преобразует их в целые числа; вам остаётся только сохранить их. (Или сделать что-нибудь ещё; очевидно, для этого примера обратный вызов не нужен.)
Пример обратного вызова 6: переменное число аргументов
Всё становится сложнее, если параметр должен принимать переменное число аргументов. В этом случае необходимо написать обратный вызов, поскольку optparse не предоставляет для этого встроенных возможностей. Также придётся самостоятельно обрабатывать некоторые тонкости традиционного разбора командной строки Unix, которые optparse обычно берёт на себя. В частности, обратные вызовы должны реализовывать традиционные правила для отдельных аргументов -- и -:
- и
--, и-могут быть аргументами параметров - отдельный
--(если он не является аргументом какого-либо параметра): прекращает обработку командной строки и отбрасывает-- - отдельный
-(если он не является аргументом какого-либо параметра): прекращает обработку командной строки, но сохраняет-(добавляет его вparser.largs)
При создании параметра, принимающего переменное число аргументов, необходимо учесть несколько тонких и сложных моментов. Конкретная реализация зависит от компромиссов, на которые вы готовы пойти в своём приложении (поэтому optparse не поддерживает такую возможность напрямую).
Тем не менее вот пример обратного вызова для параметра с переменным числом аргументов:
def vararg_callback(option, opt_str, value, parser):
assert value is None
value = []
def floatable(str):
try:
float(str)
return True
except ValueError:
return False
for arg in parser.rargs:
# stop on --foo like options
if arg[:2] == "--" and len(arg) > 2:
break
# stop on -a, but not on -3 or -3.0
if arg[:1] == "-" and len(arg) > 1 and not floatable(arg):
break
value.append(arg)
del parser.rargs[:len(value)]
setattr(parser.values, option.dest, value)
...
parser.add_option("-c", "--callback", dest="vararg_attr",
action="callback", callback=vararg_callback)
Расширение optparse
Поскольку двумя основными факторами, определяющими, как optparse интерпретирует параметры командной строки, являются действие и тип каждого параметра, наиболее вероятный способ расширения — добавить новые действия и новые типы.
Добавление новых типов
Чтобы добавить новые типы, необходимо определить собственный подкласс класса Option из optparse. Этот класс имеет два атрибута, определяющих типы optparse: TYPES и TYPE_CHECKER.
-
Option.TYPES -
Кортеж имён типов; в подклассе достаточно определить новый кортеж
TYPES, дополняющий стандартный.
-
Option.TYPE_CHECKER -
Словарь, сопоставляющий имена типов функциям проверки типов. Функция проверки типа имеет следующую сигнатуру:
def check_mytype(option, opt, value)
где
option— экземплярOption,opt— строка параметра (например,-f), аvalue— строка из командной строки, которую нужно проверить и преобразовать в требуемый тип.check_mytype()должна возвращать объект предполагаемого типаmytype. Значение, возвращённое функцией проверки типа, будет помещено в экземпляр OptionValues, возвращаемый методомOptionParser.parse_args(), либо передано обратному вызову в качестве параметраvalue.Если при проверке возникнут проблемы, функция проверки типа должна вызвать исключение
OptionValueError.OptionValueErrorпринимает один строковый аргумент, который без изменений передаётся методуerror()классаOptionParser. Этот метод добавляет перед ним имя программы и строку"error:", выводит всё в stderr, а затем завершает процесс.
Вот забавный пример, демонстрирующий добавление типа параметра "complex" для разбора комплексных чисел в стиле Python в командной строке. (Теперь пример ещё забавнее, поскольку в optparse 1.3 появилась встроенная поддержка комплексных чисел, но не будем об этом.)
Сначала необходимые импорты:
from copy import copy from optparse import Option, OptionValueError
Сначала нужно определить функцию проверки типа, поскольку позднее на неё будет ссылка (в атрибуте класса TYPE_CHECKER подкласса Option):
def check_complex(option, opt, value):
try:
return complex(value)
except ValueError:
raise OptionValueError(
"option %s: invalid complex value: %r" % (opt, value))
Наконец, подкласс Option:
class MyOption (Option):
TYPES = Option.TYPES + ("complex",)
TYPE_CHECKER = copy(Option.TYPE_CHECKER)
TYPE_CHECKER["complex"] = check_complex
(Если бы мы не создали копию copy() для Option.TYPE_CHECKER, мы изменили бы атрибут TYPE_CHECKER класса Option в optparse. Разумеется, в Python ничто не мешает вам так поступить, кроме хороших манер и здравого смысла.)
Вот и всё! Теперь можно написать скрипт, использующий новый тип параметра так же, как любой другой скрипт на основе optparse, за исключением того, что нужно указать OptionParser использовать MyOption вместо Option:
parser = OptionParser(option_class=MyOption)
parser.add_option("-c", type="complex")
Кроме того, можно создать собственный список параметров и передать его OptionParser; если не использовать add_option() описанным выше способом, указывать OptionParser, какой класс параметров использовать, не нужно:
option_list = [MyOption("-c", action="store", type="complex", dest="c")]
parser = OptionParser(option_list=option_list)
Добавление новых действий
Добавлять новые действия немного сложнее, поскольку нужно понимать, что в optparse действия делятся на несколько категорий:
- Действия «store»
-
Действия, в результате которых
optparseсохраняет значение в атрибут текущего экземпляра OptionValues; для таких параметров при создании Option необходимо указать атрибутdest. - Действия с типом
-
Действия, которые получают значение из командной строки и ожидают, что оно будет иметь определённый тип; точнее, что это будет строка, которую можно преобразовать в определённый тип. Для таких параметров при создании Option необходимо указать атрибут
type.
Эти категории пересекаются: к стандартным действиям «store» относятся "store", "store_const", "append" и "count", а к стандартным действиям с типом — "store", "append" и "callback".
Добавляя действие, необходимо отнести его к категории, указав его как минимум в одном из следующих атрибутов класса Option (все они представляют собой списки строк):
-
Option.ACTIONS -
Все действия должны быть перечислены в ACTIONS.
-
Option.STORE_ACTIONS -
Действия «store» дополнительно перечисляются здесь.
-
Option.TYPED_ACTIONS -
Действия с типом дополнительно перечисляются здесь.
-
Option.ALWAYS_TYPED_ACTIONS -
Действия, которым всегда требуется тип (то есть параметры которых всегда принимают значение), дополнительно перечисляются здесь. Это нужно лишь для того, чтобы
optparseназначал тип по умолчанию,"string", параметрам без явно указанного типа, если их действие перечислено вALWAYS_TYPED_ACTIONS.
Чтобы реализовать новое действие, необходимо переопределить метод take_action() класса Option и добавить вариант, распознающий это действие.
Например, добавим действие "extend". Оно похоже на стандартное действие "append", но вместо получения одного значения из командной строки и добавления его к существующему списку "extend" будет получать несколько значений в одной строке, разделённых запятыми, и расширять ими существующий список. То есть, если --names — параметр "extend" типа "string", то следующая командная строка
--names=foo,bar --names blah --names ding,dong
приведёт к получению списка
["foo", "bar", "blah", "ding", "dong"]
Снова определим подкласс Option:
class MyOption(Option):
ACTIONS = Option.ACTIONS + ("extend",)
STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",)
def take_action(self, action, dest, opt, value, values, parser):
if action == "extend":
lvalue = value.split(",")
values.ensure_value(dest, []).extend(lvalue)
else:
Option.take_action(
self, action, dest, opt, value, values, parser)
Особенности, на которые стоит обратить внимание:
-
"extend"требует значение в командной строке и сохраняет его, поэтому действие включается и вSTORE_ACTIONS, и вTYPED_ACTIONS. - чтобы
optparseназначал тип"string"по умолчанию для действий"extend", мы также включаем действие"extend"вALWAYS_TYPED_ACTIONS. -
MyOption.take_action()реализует только это новое действие и передаёт управление обратноOption.take_action()для стандартных действийoptparse. -
values— экземпляр класса optparse_parser.Values, предоставляющего очень полезный методensure_value(). По сути,ensure_value()— этоgetattr()с защитой от ошибок; он вызывается следующим образом:values.ensure_value(attr, value)
Если атрибут
attrобъектаvaluesне существует или равенNone, то ensure_value() сначала присваивает ему значениеvalue, а затем возвращаетvalue. Это очень удобно для таких действий, как"extend","append"и"count": все они накапливают данные в переменной и предполагают, что эта переменная имеет определённый тип (список для первых двух и целое число для последнего). Использованиеensure_value()избавляет скрипты, применяющие ваше действие, от необходимости задавать значение по умолчанию для соответствующих назначений параметров: достаточно оставить значение по умолчанию равнымNone, аensure_value()позаботится о том, чтобы при необходимости оно было корректным.
Исключения
-
exception optparse.OptionError -
Вызывается, если экземпляр
Optionсоздан с недопустимыми или противоречивыми аргументами.
-
exception optparse.OptionConflictError -
Вызывается, если в
OptionParserдобавлены конфликтующие параметры.
-
exception optparse.OptionValueError -
Вызывается, если в командной строке обнаружено недопустимое значение параметра.
-
exception optparse.BadOptionError -
Вызывается, если в командной строке передан недопустимый параметр.
-
exception optparse.AmbiguousOptionError -
Вызывается, если в командной строке передан неоднозначный параметр.
© 2001 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.14/library/optparse.html