Документация Python неофициальный перевод
Содержание страницы

optparse – Парсер параметров командной строкиoptparse – Parser for command line options

Исходный код: Lib/optparse.py

Устарело с версии 3.2: Модуль optparse устарел и не будет развиваться дальше; разработка будет продолжена с модулем argparse.


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]).

ПредысторияBackground

optparse был явно спроектирован для поощрения создания программ с простыми и стандартными интерфейсами командной строки. Для этого он поддерживает только самые распространённые синтаксис и семантику командной строки, традиционно используемые в Unix. Если вы не знакомы с этими соглашениями, прочитайте этот раздел, чтобы ознакомиться с ними.

ТерминологияTerminology

аргумент

строка, введенная в командной строке и переданная оболочкой в 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 являются позиционными аргументами.

Для чего нужны опции?What are options for?

Опции используются для предоставления дополнительной информации для настройки или кастомизации выполнения программы. Если это не было очевидно, опции обычно необязательны. Программа должна нормально работать вообще без опций. (Возьмите случайную программу из инструментария Unix или GNU. Может ли она работать без каких-либо опций и при этом иметь смысл? Главные исключения – find, tar и dd – все они мутанты-чудаки, которые по праву критикуются за нестандартный синтаксис и запутанные интерфейсы.)

Многие хотят, чтобы в их программах были «обязательные опции». Подумайте об этом. Если это обязательно, значит, это не необязательно! Если есть информация, которая absolutely необходима вашей программе для успешного выполнения, для этого существуют позиционные аргументы.

В качестве примера хорошего дизайна интерфейса командной строки рассмотрим скромную утилиту cp для копирования файлов. Копировать файлы без указания назначения и хотя бы одного источника не имеет особого смысла. Поэтому cp завершается с ошибкой, если запустить ее без аргументов. Однако у нее гибкий, полезный синтаксис, который вообще не требует опций:

cp SOURCE DEST
cp SOURCE ... DEST-DIR

На этом можно многого добиться. Большинство реализаций cp предоставляют множество опций для точной настройки копирования: можно сохранять права и время модификации, не следовать симлинкам, спрашивать перед перезаписью существующих файлов и т.д. Но ничто из этого не отвлекает от основной задачи cp – скопировать один файл в другой или несколько файлов в другой каталог.

Для чего нужны позиционные аргументы?What are positional arguments for?

Позиционные аргументы предназначены для тех частей информации, которые absolutely и однозначно необходимы вашей программе для работы.

Хороший пользовательский интерфейс должен иметь как можно меньше абсолютных требований. Если вашей программе требуется 17 различных частей информации для успешного запуска, не имеет большого значения как вы получаете эту информацию от пользователя – большинство людей сдадутся и уйдут, так и не запустив программу. Это справедливо независимо от того, является ли интерфейс командной строкой, файлом конфигурации или графическим интерфейсом: если вы предъявляете столько требований к пользователям, большинство из них просто сдадутся.

Короче говоря, старайтесь минимизировать объем информации, которую пользователи absolutely обязаны предоставить – используйте разумные значения по умолчанию, когда это возможно. Конечно, вы также хотите сделать свои программы достаточно гибкими. Для этого и нужны опции. Опять же, неважно, являются ли они записями в файле конфигурации, виджетами в диалоге «Настройки» графического интерфейса или опциями командной строки – чем больше опций вы реализуете, тем гибче становится ваша программа, и тем сложнее становится ее реализация. Слишком большая гибкость тоже имеет недостатки; слишком много опций может перегрузить пользователей и сделать ваш код гораздо сложнее в поддержке.

Учебное руководствоTutorial

Хотя 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 (destination) и help. Из них action является самым основным.

Понимание действий опцийUnderstanding option actions

Действия сообщают optparse, что делать, когда он встречает опцию в командной строке. Существует фиксированный набор действий, встроенных в optparse; добавление новых действий – продвинутая тема, рассматриваемая в разделе Расширение optparse. Большинство действий говорят optparse сохранить значение в некоторую переменную – например, взять строку из командной строки и сохранить её в атрибуте options.

Если не указано действие опции, optparse по умолчанию использует store.

Действие storeThe store action

Наиболее распространенное действие опции – 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.

Обработка булевых (флаговых) опцийHandling boolean (flag) options

Флаговые опции – установка переменной в 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.

Другие действияOther actions

Некоторые другие действия, поддерживаемые optparse:

"store_const"

сохранить постоянное значение, предварительно заданное через Option.const

"append"

добавить аргумент этой опции в список

"count"

увеличить счётчик на единицу

"callback"

вызвать указанную функцию

Они описаны в разделе Справочное руководство, и в разделе Колбэки параметров.

Значения по умолчаниюDefault values

Все приведённые выше примеры предполагают установку некоторой переменной («назначения») при обнаружении определённых параметров командной строки. Что произойдёт, если эти параметры никогда не встретятся? Поскольку мы не указали значения по умолчанию, все они будут установлены в 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()

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

Генерация справкиGenerating help

Возможность 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.

Группировка параметровGrouping Options

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

Группа параметров создаётся с помощью класса OptionGroup:

class optparse.OptionGroup(parser, title, description=None)

где

  • parser – это экземпляр OptionParser, в который будет вставлена группа

  • title – это заголовок группы

  • description (необязательно) – это подробное описание группы

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.

Печать строки версииPrinting a version string

Подобно краткой строке использования, 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(), но возвращает строку версии вместо её вывода.

Как optparse обрабатывает ошибкиHow optparse handles errors

Существует два широких класса ошибок, с которыми приходится иметь дело 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().

Собираем всё вместеPutting it all together

Вот как обычно выглядят скрипты на основе 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()

Справочное руководствоReference Guide

Создание парсераCreating the parser

Первым шагом при использовании optparse является создание экземпляра OptionParser.

class optparse.OptionParser(...)

Конструктор OptionParser не требует обязательных аргументов, но принимает ряд необязательных именованных аргументов. Их всегда следует передавать как именованные аргументы, т.е. не полагаться на порядок объявления аргументов.

usage (по умолчанию: "%prog [options]")

Краткая справка по использованию, выводимая при неправильном запуске программы или по запросу справки. Когда optparse выводит строку использования, он заменяет %prog на os.path.basename(sys.argv[0]) (или на prog, если был передан соответствующий именованный аргумент). Чтобы отключить сообщение об использовании, передайте специальное значение optparse.SUPPRESS_USAGE.

option_list (по умолчанию: [])

Список объектов Option для заполнения парсера. Опции из option_list добавляются после любых опций из standard_option_list (атрибута класса, который может быть установлен подклассами OptionParser), но перед опциями версии и справки. Устарело; вместо этого используйте add_option() после создания парсера.

option_class (по умолчанию: optparse.Option)

Класс, используемый при добавлении опций в парсер в add_option().

version (по умолчанию: None)

Строка версии, выводимая по запросу опции версии. Если задать истинное значение для version, optparse автоматически добавляет опцию версии с единственной строкой опции --version. Подстрока %prog заменяется так же, как для usage.

conflict_handler (по умолчанию: "error")

Определяет, что делать, когда в парсер добавляются опции с конфликтующими строками опций; см. раздел Конфликты между опциями.

description (по умолчанию: None)

Абзац текста с кратким обзором программы. optparse переформатирует этот абзац под текущую ширину терминала и выводит его по запросу справки (после usage, но перед списком опций).

formatter (по умолчанию: новый IndentedHelpFormatter)

Экземпляр optparse.HelpFormatter, используемый для вывода текста справки. optparse предоставляет два конкретных класса для этой цели: IndentedHelpFormatter и TitledHelpFormatter.

add_help_option (по умолчанию: True)

Если истина, optparse добавит в парсер опцию справки (со строками опций -h и --help).

prog

Строка, используемая при замене %prog в usage и version вместо os.path.basename(sys.argv[0]).

epilog (по умолчанию: None)

Абзац текста справки, выводимый после справки по опциям.

Заполнение парсераPopulating the parser

Есть несколько способов заполнить парсер опциями. Предпочтительный способ – использовать 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 напрямую.)

Определение опцийDefining options

Каждый экземпляр 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, поясняющее ошибку.

Атрибут action опции определяет, что делает 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). Аргументы опций (и различные другие значения) сохраняются как атрибуты этого объекта, согласно атрибуту опции 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 – единственный, который имеет смысл для всех опций.

Атрибуты опцийOption attributes

Следующие атрибуты опций могут быть переданы как именованные аргументы в OptionParser.add_option(). Если передать атрибут опции, который не является релевантным для конкретной опции, или не указать обязательный атрибут опции, optparse вызовет OptionError.

Option.action

(по умолчанию: "store")

Determines optparse’s behaviour when this option is seen on the command line; the available options are documented here.

Option.type

(по умолчанию: "string")

The argument type expected by this option (e.g., "string" or "int"); the available option types are documented here.

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

For options with action "callback", the callable to call when this option is seen. See section Option Callbacks for detail on the arguments passed to the callable.

Option.callback_args
Option.callback_kwargs

Дополнительные позиционные и именованные аргументы, передаваемые в callback после четырёх стандартных аргументов колбэка.

Option.help

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

Option.metavar

(по умолчанию: выводится из строк опций)

Stand-in for the option argument(s) to use when printing help text. See section Tutorial for an example.

Стандартные действия опцийStandard option actions

Различные действия опций имеют слегка разные требования и эффекты. У большинства действий есть несколько соответствующих атрибутов опции, которые вы можете указать, чтобы управлять поведением optparse; некоторые имеют обязательные атрибуты, которые необходимо указывать для любой опции, использующей это действие.

  • "store" [относится: type, dest, nargs, choices]

    The option must be followed by an argument, which is converted to a value according to type and stored in dest. If nargs > 1, multiple arguments will be consumed from the command line; all will be converted according to type and stored to dest as a tuple. See the Standard option types section.

    Если указан choices (список или кортеж строк), тип по умолчанию "choice".

    Если type не указан, по умолчанию используется "string".

    Если dest не указан, optparse выводит destination из первой длинной строки опции (например, --foo-bar подразумевает foo_bar). Если длинных строк опций нет, optparse выводит destination из первой короткой строки опции (например, -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
    
    # обычно опция справки добавляется автоматически, но её можно
    # подавить, используя аргумент add_help_option
    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"

    Выводит номер версии, переданный OptionParser, в stdout и завершает работу. Номер версии форматируется и выводится методом print_version() объекта OptionParser. Обычно актуально только если аргумент version передан конструктору OptionParser. Как и для опций help, version редко создаются вручную, так как optparse добавляет их автоматически при необходимости.

Стандартные типы опцийStandard option types

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, если указана недопустимая строка.

Разбор аргументовParsing arguments

Весь смысл создания и заполнения OptionParser заключается в вызове его метода parse_args():

(options, args) = parser.parse_args(args=None, values=None)

где входные параметры:

args

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

values

объект optparse.Values для хранения аргументов параметров (по умолчанию: новый экземпляр Values) – если передать существующий объект, значения параметров по умолчанию не будут в нем инициализированы

а возвращаемые значения –

options

тот же объект, который был передан как values, или экземпляр optparse.Values, созданный optparse

args

оставшиеся позиционные аргументы после обработки всех опций

Наиболее распространённый способ использования – не указывать ни один из именованных аргументов. Если передать values, он будет изменён многократными вызовами setattr() (примерно по одному на каждый аргумент опции, сохраняемый в целевой атрибут) и возвращён parse_args().

Если parse_args() обнаруживает ошибки в списке аргументов, он вызывает метод error() объекта OptionParser с подходящим сообщением об ошибке для конечного пользователя. В итоге процесс завершается с кодом возврата 2 (традиционный код выхода Unix для ошибок командной строки).

Запросы и изменение вашего парсера опцийQuerying and manipulating your option parser

Поведение парсера опций по умолчанию можно слегка настроить, а также можно заглянуть внутрь парсера и посмотреть, что там есть. 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.

Конфликты между опциямиConflicts between options

Если быть невнимательным, легко определить опции с конфликтующими строками опций:

parser.add_option("-n", "--dry-run", ...)
...
parser.add_option("-n", "--noisy", ...)

(Это особенно актуально, если определён собственный подкласс OptionParser с некоторыми стандартными опциями.)

При каждом добавлении опции optparse проверяет наличие конфликтов с существующими опциями. Если они обнаружены, вызывается текущий механизм обработки конфликтов. Механизм обработки конфликтов можно задать либо в конструкторе:

parser = OptionParser(..., conflict_handler=handler)

или отдельным вызовом:

parser.set_conflict_handler(handler)

Доступные обработчики конфликтов:

"error" (по умолчанию)

считать конфликты опций программной ошибкой и возбуждать 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

ОчисткаCleanup

Экземпляры OptionParser содержат несколько циклических ссылок. Это не должно быть проблемой для сборщика мусора Python, но можно явно разорвать циклические ссылки, вызвав destroy() для вашего OptionParser после завершения работы с ним. Это особенно полезно в долго работающих приложениях, где из OptionParser достижимы большие графы объектов.

Другие методыOther methods

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")    # переопределено ниже
parser.add_option("--novice", action="store_const",
                  dest="mode", const="novice",
                  default="advanced")  # переопределяет вышеуказанную настройку

Чтобы избежать этой путаницы, используйте 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")

Колбэки опцийOption Callbacks

Когда встроенных действий и типов optparse недостаточно, есть два варианта: расширить optparse или определить опцию-колбэк. Расширение optparse более универсально, но для многих простых случаев избыточно. Зачастую простого колбэка вполне достаточно.

Определение опции-колбэка состоит из двух шагов:

  • определить саму опцию с помощью действия "callback"

  • написать колбэк – функцию (или метод), которая принимает как минимум четыре аргумента, как описано ниже

Определение опции-колбэкаDefining a callback option

Как всегда, проще всего определить опцию-колбэк с помощью метода 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

словарь дополнительных именованных аргументов, передаваемых колбэку

Как вызываются колбэкиHow callbacks are called

Все колбэки вызываются следующим образом:

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.

Возбуждение ошибок в колбэкеRaising errors in a callback

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

Пример колбэка 1: тривиальный колбэкCallback example 1: trivial callback

Вот пример опции-колбэка, которая не принимает аргументов и просто записывает факт своего появления:

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: проверка порядка опцийCallback example 2: check option order

Вот чуть более интересный пример: запоминать, что -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: проверка порядка параметров (обобщённый)Callback example 3: check option order (generalized)

Если требуется повторно использовать этот колбэк для нескольких похожих опций (устанавливать флаг, но выдавать ошибку, если -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: проверка произвольного условияCallback example 4: check arbitrary condition

Конечно, можно задать любое условие – вы не ограничены проверкой значений уже определённых параметров. Например, если есть параметры, которые не должны вызываться в полнолуние, достаточно сделать так:

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: фиксированное число аргументовCallback example 5: fixed arguments

Ситуация становится немного интереснее, когда определяется параметр-колбэк с фиксированным числом аргументов. Указание, что параметр-колбэк принимает аргументы, аналогично определению параметра "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: переменное число аргументовCallback example 6: variable arguments

Всё становится сложнее, когда требуется, чтобы параметр принимал переменное число аргументов. В этом случае нужно писать колбэк, так как 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:
        # останавливаться на опциях вида --foo
        if arg[:2] == "--" and len(arg) > 2:
            break
        # останавливаться на -a, но не на -3 или -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)

Расширение optparseExtending optparse

Поскольку двумя основными управляющими факторами того, как optparse интерпретирует параметры командной строки, являются действие и тип каждого параметра, наиболее вероятное направление расширения – добавление новых действий и новых типов.

Добавление новых типовAdding new types

Чтобы добавить новые типы, нужно определить собственный подкласс класса 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)

Добавление новых действийAdding new actions

Добавление новых действий немного сложнее, потому что нужно понимать, что optparse разделяет действия на несколько категорий:

«store»-действия

действия, в результате которых optparse сохраняет значение в атрибут текущего экземпляра OptionValues; для таких опций в конструктор Option требуется передать атрибут dest.

«typed»-действия

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

Это пересекающиеся множества: к стандартным «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.

Чтобы реализовать новое действие, нужно переопределить метод 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, а затем возвращает значение. Это очень удобно для действий вроде "extend", "append" и "count", все из которых накапливают данные в переменной и ожидают, что переменная будет определённого типа (список для первых двух, целое число для последнего). Использование ensure_value() означает, что сценарии, использующие ваше действие, могут не беспокоиться об установке значения по умолчанию для соответствующих мест назначения опций; они могут просто оставить значение по умолчанию равным None, и ensure_value() позаботится о том, чтобы всё было правильно, когда это потребуется.