optparse — Парсер командной строки
Новая версия с 2.3.
Устаревшая с версии 2.7: Модуль optparse устарел и дальнейшей разработки не будет; разработка будет продолжена в модуле argparse.
Исходный код: Lib/optparse.py
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]).
1. Предыстория
optparse была разработана специально для поощрения создания программ с простыми, традиционными интерфейсами командной строки. В этой связи она поддерживает только наиболее распространённый синтаксис и семантику командной строки, традиционно используемые в Unix. Если вы не знакомы с этими соглашениями, прочитайте этот раздел, чтобы ознакомиться с ними.
1.1. Терминология
- аргумент
-
строка, введённая в командной строке и переданная оболочкой
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, и никогда не будут. Это сделано намеренно: первые три нестандартны ни в одной среде, а последние имеют смысл только если вы исключительно ориентируетесь на VMS, MS-DOS и/или Windows. - дефис, за которым следуют несколько букв, например
- аргумент опции
-
аргумент, который следует за опцией, тесно связан с ней и потребляется из списка аргументов, когда эта опция есть. В
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 — позиционные аргументы.
1.2. Для чего нужны опции?
Опции используются для предоставления дополнительной информации для настройки или изменения выполнения программы. Если это не было очевидно, опции обычно необязательны. Программа должна быть способна работать и без опций. (Выберите случайную программу из наборов инструментов Unix или GNU. Может ли она работать без опций и при этом иметь смысл? Главные исключения — find, tar, и dd—все они являются мутантными аномалиями, которые справедливо подвергались критике за их нестандартный синтаксис и непонятные интерфейсы.)
Многие хотят, чтобы их программы имели «обязательные опции». Подумайте об этом. Если это обязательно, значит оно не необязательно! Если какой-то элемент информации вашей программе абсолютно необходим для успешного выполнения, для этого предназначены позиционные аргументы.
В качестве примера хорошего дизайна интерфейса командной строки рассмотрите утилиту cp для копирования файлов. Не имеет большого смысла пытаться копировать файлы без указания места назначения и, по крайней мере, одного исходного файла. Поэтому cp завершается неудачей, если вы запускаете её без аргументов. Однако у неё есть гибкий, полезный синтаксис, не требующий никаких опций:
cp SOURCE DEST cp SOURCE ... DEST-DIR
Вы можете обойтись и так. Большинство реализаций cp предоставляют множество опций для точной настройки копирования файлов: вы можете сохранить режим и время последнего изменения, избегать следования символам, спрашивать перед заменой существующих файлов и т. д. Но всё это не отвлекает от основной задачи cp, которая заключается в копировании либо одного файла в другой, либо нескольких файлов в другую директорию.
1.3. Для чего нужны позиционные аргументы?
Позиционные аргументы предназначены для той информации, которую ваша программа абсолютно, положительно требует для выполнения.
Хороший пользовательский интерфейс должен иметь как можно меньше абсолютных требований. Если ваша программе требуется 17 различных элементов информации для успешного выполнения, это не имеет большого значения — как вы получите эту информацию от пользователя — большинство людей сдадутся и уйдут, прежде чем успешно запустить программу. Это относится как к интерфейсу командной строки, так и к файлу конфигурации или графическому интерфейсу пользователя: если вы предъявите пользователям столько требований, большинство из них просто сдадутся.
Короче говоря, старайтесь минимизировать количество информации, которую пользователи обязательно должны предоставить — используйте разумные значения по умолчанию всякий раз, когда это возможно. Конечно, вы также хотите сделать свои программы достаточно гибкими. Для этого предназначены параметры. Опять же, неважно, являются ли они записями в файле конфигурации, виджетами в диалоговом окне «Настройки» графического интерфейса пользователя или параметрами командной строки — чем больше параметров вы реализуете, тем более гибкой будет ваша программа, и тем сложнее станет ее реализация. Конечно, чрезмерная гибкость также имеет свои недостатки; слишком много параметров может перегрузить пользователей и сильно усложнить поддержку вашего кода.
2. Руководство
Хотя 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 является наиболее фундаментальным.
2.1. Понимание действий с параметрами
Действия сообщают optparse что делать при обнаружении параметра в командной строке. В optparse существует фиксированный набор действий; добавление новых действий является продвинутой темой, рассмотренной в разделе Расширение optparse. Большинство действий сообщают optparse о хранении значения в какой-либо переменной — например, взять строку из командной строки и сохранить ее в атрибуте options.
Если вы не укажете действие с параметром, optparse по умолчанию использует store.
2.2. Действие 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 также включает встроенные типы long и complex. Добавление типов описано в разделе Расширение optparse.
2.3. Обработка логических (флаговых) параметров
Флаговые параметры — установка переменной в 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.
2.4. Другие действия
Некоторые другие действия, поддерживаемые optparse, это:
-
"store_const" -
хранение постоянного значения
-
"append" -
добавление аргумента этого параметра в список
-
"count" -
увеличение счетчика на единицу
-
"callback" -
вызов указанной функции
Эти действия рассматриваются в разделе Руководство, Руководство и разделе Обратные вызовы параметров.
2.5. Значения по умолчанию
Все приведенные выше примеры предполагают установку некоторой переменной (пункт назначения), когда видны определенные параметры командной строки. Что произойдет, если эти параметры не будут видны? Поскольку мы не предоставили значений по умолчанию, они все будут установлены в None. Это обычно нормально, но иногда вы хотите больше контроля. optparse позволяет вам указать значение по умолчанию для каждого пункта назначения, которое назначается до разбора командной строки.
Вначале рассмотрим пример с подробным/неподробным выводом. Если мы хотим, чтобы 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()
Как и прежде, последнее указанное значение для данного назначения — это то, которое учитывается. Для большей ясности, попробуйте использовать один из способов задания значений по умолчанию, а не оба.
2.6. Генерация справки
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заботится о переносе строк и делает вывод справки удобным. -
параметры, которые принимают значение, указывают этот факт в автоматически сгенерированном сообщении справки, например, для параметра «режим»:
-m MODE, --mode=MODE
Здесь «РЕЖИМ» называется метапеременной: она обозначает аргумент, который пользователь должен предоставить для
-m/--mode. По умолчаниюoptparseпреобразует имя переменной назначения в верхний регистр и использует его для метапеременной. Иногда это не то, что вам нужно — например, параметр--filenameявно задаётmetavar="FILE", что приводит к этому автоматически сгенерированному описанию параметра:-f FILE, --filename=FILE
Это важно не только для экономии места, но и для: вручную написанный текст справки использует метапеременную
FILEдля того, чтобы подсказать пользователю связь между полуформальным синтаксисом-f FILEи неформальным семантическим описанием «записать вывод в ФАЙЛ». Это простой, но эффективный способ сделать текст справки более понятным и полезным для конечных пользователей.
Введено в версии 2.4: Параметры, имеющие значение по умолчанию, могут включать %default в строке справки — optparse заменит её на str() значения по умолчанию параметра. Если параметр не имеет значения по умолчанию (или значение по умолчанию — None), %default расширяется до none.
2.6.1. Группировка параметров
При работе со многими параметрами удобно сгруппировать их для лучшего вывода справки. 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.
2.7. Вывод строки версии
Аналогично короткой строке использования, optparse также может вывести строку версии вашей программы. Вам нужно предоставить строку как аргумент version объекту OptionParser:
parser = OptionParser(usage="%prog [-f] [-q]", version="%prog 1.0")
%prog расширяется так же, как и в usage. Помимо этого, version может содержать всё, что вам нужно. При её предоставлении optparse автоматически добавляет параметр --version в ваш парсер. Если он встречает этот параметр в командной строке, он расширяет вашу строку version (заменив %prog), выводит её в stdout и завершает работу.
Например, если ваш скрипт называется /usr/bin/foo:
$ /usr/bin/foo --version foo 1.0
Следующие два метода могут использоваться для вывода и получения строки version:
-
OptionParser.print_version(file=None) -
Выводит сообщение версии текущей программы (
self.version) в file (по умолчанию stdout). Как и сprint_usage(), любое вхождение%progвself.versionзаменяется именем текущей программы. Ничего не делает, еслиself.versionпусто или не определено.
-
OptionParser.get_version() -
Аналогично
print_version(), но возвращает строку версии вместо вывода.
2.8. Как 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().
2.9. Объединение всего
Вот как обычно выглядят скрипты, основанные на 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()
3. Справочник
3.1. Создание анализатора
Первый шаг при использовании 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) -
Если True,
optparseдобавит опцию помощи (со строками опций-hи--help) в анализатор. -
prog -
Строка, используемая при расширении
%progвusageиversionвместоos.path.basename(sys.argv[0]). -
epilog (default: None) -
Абзац текста справки, который будет напечатан после текста справки по опциям.
-
3.2. Заполнение анализатора
Есть несколько способов заполнения анализатора опциями. Предпочтительный способ — использование OptionParser.add_option(), как показано в разделе Учебник. add_option() может быть вызван двумя способами:
- передача экземпляра Option (как возвращаемого
make_option()) - передача любой комбинации позиционных и именованных аргументов, приемлемых для
make_option()(то есть для конструктора Option), и он создаст для вас экземпляр Option
Другой вариант — передать список предварительно созданных экземпляров Option в конструктор OptionParser, как в:
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 напрямую.)
3.3. Определение опций
Каждый экземпляр 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" -
хранение константного значения
-
"store_true" -
хранение истинного значения
-
"store_false" -
хранение ложного значения
-
"append" -
добавление аргумента этой опции в список
-
"append_const" -
добавление константы в список
-
"count" -
увеличение счётчика на единицу
-
"callback" -
вызов указанной функции
-
"help" -
вывод сообщения об использовании, включающего все опции и документацию к ним
(Если вы не указываете действие, по умолчанию используется
"store". Для этого действия вы также можете указать атрибуты опцииtypeиdest; см. Стандартные действия опций.) -
Как вы можете видеть, большинство действий предполагают хранение или обновление значения где-либо. optparse всегда создает для этого специальный объект, обычно называемый options (это экземпляр optparse.Values). Аргументы опций (и различные другие значения) хранятся в качестве атрибутов этого объекта в соответствии с атрибутом опции 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 — единственный атрибут, который имеет смысл для всех опций.
3.4. Атрибуты опций
Следующие атрибуты опций могут быть переданы в качестве именованных аргументов методу 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 -
(по умолчанию: выводится из строк опций)
Заместитель для аргумента(ов) опции для использования при печати текста справки. Пример см. в разделе Руководство.
3.5. Стандартные действия опций
Различные действия опций имеют несколько различные требования и эффекты. Большинство действий имеют несколько соответствующих атрибутов опций, которые вы можете указать для управления поведением optparse; некоторые имеют необходимые атрибуты, которые вы должны указать для любой опции, использующей это действие.
-
"store"[relevant: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"[required:const; relevant: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"[relevant:dest]Особый случай
"store_const", который сохраняет истинное значение вdest. -
"store_false"[relevant:dest]Как и
"store_true", но хранит ложное значение.Пример:
parser.add_option("--clobber", action="store_true", dest="clobber") parser.add_option("--no-clobber", action="store_false", dest="clobber") -
"append"[relevant:type,dest,nargs,choices]Параметр должен следовать за аргументом, который добавляется к списку в
dest. Если значение по умолчанию дляdestне указано, при первом встрече данного параметра в командной строкеoptparseавтоматически создаёт пустой список. Еслиnargs> 1, потребляются несколько аргументов, и кdestдобавляется кортеж длиныnargs.Значения по умолчанию для
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"[required:const; relevant:dest]Как
"store_const", но значениеconstдобавляется кdest; как и в"append",destпо умолчанию равноNone, и пустой список создается автоматически при первом обнаружении параметра. -
"count"[relevant:dest]Увеличивает целое число, хранящееся в
dest. Если значение по умолчанию не указано,destустанавливается в ноль перед увеличением при первом встрече.Пример:
parser.add_option("-v", action="count", dest="verbosity")При первом встрече
-vв командной строкеoptparseвыполняет эквивалент:options.verbosity = 0 options.verbosity += 1
Каждое последующее вхождение
-vприводит кoptions.verbosity += 1
-
"callback"[required:callback; relevant: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ко всем парсерам параметров, поэтому обычно создавать его не нужно.Пример:
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в командной строке, он выведет что-то вроде следующего сообщения справки в стандартный вывод (предполагая, что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"Выводит номер версии, переданный OptionParser, в стандартный вывод и завершает выполнение. Номер версии фактически форматируется и выводится методом
print_version()OptionParser. Обычно актуально только если аргументversionпередан в конструктор OptionParser. Как и с параметрамиhelp, вы редко будете создавать параметрыversion, так какoptparseдобавляет их автоматически при необходимости.
3.6. Стандартные типы параметров
optparse имеет шесть встроенных типов параметров: "string", "int", "long", "choice", "float" и "complex" . Если вам нужно добавить новые типы параметров, см. раздел Расширение optparse.
Аргументы строковых параметров не проверяются и не преобразуются каким-либо образом: текст из командной строки сохраняется в целевом объекте (или передается в обратный вызов) как есть.
Целочисленные аргументы (типа "int" или "long" ) анализируются следующим образом:
- если число начинается с
0x, оно анализируется как шестнадцатеричное число - если число начинается с
0, оно анализируется как восьмеричное число - если число начинается с
0b, оно анализируется как двоичное число - в противном случае число анализируется как десятичное число
Преобразование выполняется с помощью вызова либо int(), либо long() с соответствующей основой (2, 8, 10 или 16). Если это не удается, то и optparse потерпит неудачу, хотя с более полезным сообщением об ошибке.
Аргументы параметров "float" и "complex" преобразуются непосредственно с помощью float() и complex() с аналогичной обработкой ошибок.
Параметры "choice" являются подтипом параметров "string" . Атрибут choices (последовательность строк) определяет набор допустимых аргументов параметров. optparse.check_choice() сравнивает предоставленные пользователем аргументы параметров с этим списком и поднимает OptionValueError , если предоставлена недопустимая строка.
3.7. Парсинг аргументов
Вся суть создания и заполнения OptionParser заключается в вызове его метода parse_args() :
(options, args) = parser.parse_args(args=None, values=None)
где входными параметрами являются
-
args -
список аргументов для обработки (по умолчанию:
sys.argv[1:]) -
optparse.Values -
объект типа
Valuesдля хранения аргументов параметров (по умолчанию: новый экземплярValues) – если вы передаете существующий объект, значения параметров по умолчанию не будут инициализированы в нем
и значениями возврата являются
-
options -
тот же объект, что и переданный как
values, или экземпляр optparse.Values, созданныйoptparse -
args -
оставшиеся позиционные аргументы после обработки всех параметров
Наиболее распространенным случаем использования является передача ни одного ключевого аргумента. Если вы передаете values , он будет модифицирован с помощью повторяющихся вызовов setattr() (приблизительно один для каждого аргумента параметра, сохраненного в целевом объекте параметра) и возвращен parse_args().
Если parse_args() обнаруживает какие-либо ошибки в списке аргументов, он вызывает метод error() OptionParser с соответствующим сообщением об ошибке для конечного пользователя. Это в конечном итоге завершает выполнение вашей программы с кодом завершения 2 (традиционный код Unix для ошибок в командной строке).
3.8. Запрос и изменение парсера параметров
Поведение парсера параметров по умолчанию можно немного настроить, а также вы можете покопаться в вашем парсере параметров и увидеть, что там есть. 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.
3.9. Конфликты между параметрами
Если вы не внимательны, легко определить параметры с конфликтующими строками параметров:
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
3.10. Очистка
Экземпляры OptionParser содержат несколько циклических ссылок. Это не должно быть проблемой для сборщика мусора Python, но вы можете захотеть явно разорвать циклические ссылки, вызвав destroy() для вашего OptionParser, когда вы закончите с ним. Это особенно полезно в долгоживущих приложениях, где большие графы объектов доступны из вашего OptionParser.
3.11. Другие методы
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()является предпочтительным способом установки значений по умолчанию для опций, так как несколько опций могут использовать одно и то же назначение. Например, если несколько опций «режим» устанавливают одно и то же назначение, любая из них может установить значение по умолчанию, и последняя из них побеждает: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")
4. Обработчики опций
Когда встроенные действия и типы optparse недостаточно для ваших нужд, у вас есть два варианта: расширить optparse или определить обработчик опций. Расширение optparse более общее, но избыточно во многих простых случаях. Часто простой обработчик — всё, что вам нужно.
Для определения обработчика опций есть два шага:
- определите саму опцию с помощью действия
"callback" - напишите обработчик; это функция (или метод), принимающая как минимум четыре аргумента, как описано ниже
4.1. Определение обработчика опций
Как всегда, самый простой способ определить обработчик опций — использовать метод 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 -
словарь дополнительных именованных аргументов для передачи обработчику
4.2. Как вызываются обработчики
Все обработчики вызываются следующим образом:
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.
4.3. Выбрасывание исключений в обратном вызове
Функция обратного вызова должна генерировать исключение OptionValueError в случае проблем с опцией или её аргументами. optparse перехватывает это и завершает программу, выводит сообщение об ошибке, которое вы предоставили, в stderr. Ваше сообщение должно быть ясным, кратким, точным и указывать на ошибочную опцию. В противном случае пользователю будет сложно понять, что он сделал не так.
4.4. Пример обратного вызова 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".
4.5. Пример обратного вызова 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")
4.6. Пример обратного вызова 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.7. Пример обратного вызова 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() оставляет как упражнение для читателя.)
4.8. Пример обратного вызова 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 аргументов и преобразовании их в целые числа для вас; всё, что вам нужно сделать, это сохранить их. (Или что угодно; очевидно, вам не нужна функция обратного вызова для этого примера.)
4.9. Пример обратного вызова 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)
5. Расширение optparse
Поскольку два основных фактора, определяющих, как optparse интерпретирует опции командной строки, это действие и тип каждой опции, наиболее вероятное направление расширения — добавление новых действий и новых типов.
5.1. Добавление новых типов
Для добавления новых типов вам нужно определить собственный подкласс класса optparse’s Option class. Этот класс имеет несколько атрибутов, определяющих типы 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принимает один строковый аргумент, который передаётся как есть методуOptionParser’serror(), который в свою очередь добавляет имя программы и строку"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)
5.2. Добавление новых действий
Добавление новых действий немного сложнее, потому что вы должны понимать, что optparse имеет несколько категорий действий:
- Действия «store»
-
действия, которые приводят к тому, что
optparseсохраняет значение в атрибуте текущего экземпляра OptionValues; для этих опций требуется атрибутdest, который должен быть предоставлен в конструкторе Option. - Действия «typed»
-
действия, которые берут значение из командной строки и ожидают, что оно будет определенного типа; или же строка, которая может быть преобразована в определённый тип. Для этих опций требуется атрибут
typeв конструкторе Option.
Это перекрывающиеся множества: некоторые стандартные действия «store» — "store", "store_const", "append", и "count", в то время как стандартные действия «typed» — "store", "append", и "callback".
При добавлении действия необходимо категоризировать его, перечислив его в одном или нескольких атрибутах класса Option (все — списки строк):
-
Option.ACTIONS -
Все действия должны быть перечислены в ACTIONS.
-
Option.STORE_ACTIONS -
Действия «store» дополнительно перечислены здесь.
-
Option.TYPED_ACTIONS -
Действия «typed» дополнительно перечислены здесь.
-
Option.ALWAYS_TYPED_ACTIONS -
Действия, которые всегда принимают тип (т.е. чьи опции всегда принимают значение), дополнительно перечислены здесь. Единственный эффект заключается в том, что
optparseприсваивает тип по умолчанию"string", опциям без явного типа, чье действие указано вALWAYS_TYPED_ACTIONS.
Чтобы фактически реализовать новое действие, необходимо переопределить метод Option's take_action() и добавить случай, который распознает ваше действие.
Например, давайте добавим действие "extend". Это аналогично стандартному действию "append", но вместо того, чтобы брать одно значение из командной строки и добавлять его в существующий список, "extend" будет брать несколько значений в одной запятой, разделённой строке и расширять существующий список ими. То есть, если --names является опцией типа "extend", командная строка
--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()позаботятся о том, чтобы сделать это правильно, когда это потребуется.
© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/2.7/library/optparse.html