optparse — Парсер для параметров командной строки

Не рекомендуется, начиная с версии 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]).

Фон

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

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

аргумент

строка, введенная в командной строке и переданная оболочкой в execl() или execv(). В Python аргументы — это элементы sys.argv[1:] (sys.argv[0] — имя выполняемой программы). Unix-оболочки также используют термин «слово».

Иногда желательно заменить список аргументов, отличный от sys.argv[1:], поэтому вы должны читать «аргумент» как «элемент sys.argv[1:] или какого-либо другого списка, предоставленного вместо sys.argv[1:]».

опция

используемый аргумент для предоставления дополнительной информации для управления или настройки выполнение программы. Есть много разных синтаксисов для опций; в традиционном синтаксисе Unix представляет собой дефис («-»), за которым следует одна буква например -x или -F. Кроме того, традиционный синтаксис Unix допускает множественные параметры должны быть объединены в один аргумент, например -x -F эквивалентен -xF. Проект GNU представил --, за которым последовала серия разделенных дефисом слов, например --file или --dry-run. optparse реализует только два варианта синтаксиса.

Некоторые другие синтаксисы опций:

  • дефис, за которым следуют несколько букв, например, -pf (это не, то же самое, что несколько параметров, объединенных в один аргумент)
  • дефис, за которым следует целое слово, например -file (технически это эквивалентно предыдущему синтаксису, но обычно они не встречаются в одной и той же программе)
  • знак плюс, за которым следует одна буква, несколько букв или слово, например +f, +rgb
  • косая черта, за которой следует буква, или несколько букв, или слово, например /f, /file

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

Для чего нужны опции?

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

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

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

cp SOURCE DEST
cp SOURCE ... DEST-DIR

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

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

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

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

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

Учебник по optparse

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

Во-первых, вам нужно импортировать класс OptionParser; затем в начале основной программы создать экземпляр OptionParser:

from optparse import OptionParser
...
parser = OptionParser()

Затем вы можете приступить к определению опций. Основной синтаксис такой:

parser.add_option(opt_str, ...,
                  attr=value, ...)

Каждый опция имеет одну или несколько строк параметров, таких как -f или --file, и несколько атрибутов параметров, сообщающих optparse, чего ожидать и что делать, когда он встречает данный параметр в командной строке.

Как правило, каждая опция будет иметь, например, одну короткую строку опции и одну длинную строку опции:

parser.add_option("-f", "--file", ...)

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

Переданные в OptionParser.add_option() строки параметров, фактически являются метками для параметра, определённого этим вызовом. Для краткости мы часто будем ссылаться на столкнуться с опцией в командной строке; на самом деле optparse встречает строки опций и ищет в них опции.

После того, как все параметры определены, поручите optparse распарсить командную строку вашей программы:

(options, args) = parser.parse_args()

(Если хотите, вы можете передать пользовательский список аргументов в parse_args(), но это редко бывает необходимо: по умолчанию используется sys.argv[1:].)

parse_args() возвращает два значения:

  • options, объект, содержащий значения для всех ваших параметров. Например, если --file принимает один строковый аргумент, то options.file будет именем файла, предоставленным пользователем, или None, если пользователь не указал данный параметр.
  • args, список позиционных аргументов, оставшихся после парсинга опций.

В этом учебном разделе рассматриваются только четыре наиболее важных атрибута параметров: action, type, dest (назначение) и help. Из них action является наиболее фундаментальным.

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

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

Если вы не укажете действие параметра, optparse по умолчанию будет store.

Действие store

Наиболее распространенное действие параметра — store, указывающее optparse где взять следующий аргумент (или оставшуюся часть текущего аргумента), убедиться, что у него правильный тип, и сохраняет его в выбранном месте назначения.

Например:

parser.add_option("-f", "--file",
                  action="store", type="string", dest="filename")

Теперь создадим фальшивую командную строку и попросим optparse распарсить её:

args = ["-f", "foo.txt"]
(options, args) = parser.parse_args(args)

Когда optparse видит строку параметра -f, он использует аргумент foo.txt, и сохраняет его в options.filename. Итак, после вызова parse_args() options.filename будет "foo.txt".

Другие типы опций, поддерживаемые optparse — это int и float. Вот опция, ожидающая целочисленный аргумент:

parser.add_option("-n", type="int", dest="num")

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

Давайте разберем ещё одну фальшивую командную строку. На данный раз мы поместим аргумент опции прямо напротив опции: поскольку -n42 (один аргумент) эквивалентен -n 42 (два аргумента), код

(options, args) = parser.parse_args(["-n42"])
print(options.num)

напечатает 42.

Если вы не укажете тип, optparse предполагает string. В сочетании с тем фактом, что действие по умолчанию — store, это означает, что наш первый пример может быть намного короче:

parser.add_option("-f", "--file", dest="filename")

Если вы не укажете место назначения, optparse вычислит разумное значение по умолчанию из строк параметров: если первая длинная строка параметров — --foo-bar, то место назначения по умолчанию — foo_bar. Если длинных строк параметров нет, optparse просматривает первую короткую строку параметров: назначением по умолчанию для -f является f.

optparse также включает встроенный тип complex. Добавление типов приведено в разделе Расширение optparse.

Обработка логических (флаговых) опций

Опциональные флаги устанавливают переменную в значение истина или ложь, когда видна определенная опция. Они довольно распространены. optparse поддерживает их двумя отдельными действиями: store_true и store_false. Например, у вас есть флаг verbose, включаемый с помощью -v и отключаемый с помощью -q:

parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose")

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

Когда optparse встречает -v в командной строке, он устанавливает options.verbose в True; когда он встречает -q, options.verbose устанавливается на False.

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

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

"store_const"
сохраняет постоянное значение
"append"
добавляет аргумент опции в список
"count"
увеличивает счётчик на единицу
"callback"
вызвает указанную функцию

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

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

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

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

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

Способность 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 и неформальным семантическим описанием «записывает вывод в ФАЙЛ». . Это простой, но эффективный способ сделать текст справки более понятным и полезным для конечных пользователей.

  • параметры, имеющие значение по умолчанию, могут включать %default в строке справки, а optparse заменит его на str() значения параметра по умолчанию. Если параметр не имеет значения по умолчанию (или значение по умолчанию — None), %default расширяется до none.

Параметры группировки

При работе со многими параметрами удобно сгруппировать данные параметры для лучшего вывода справки. 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.

Печать строки версии

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

parser = OptionParser(usage="%prog [-f] [-q]", version="%prog 1.0")

%prog расширяется так же, как и usage. Кроме того, version может содержать что угодно. Когда вы его указываете, optparse автоматически добавляет в ваш парсер параметр --version. Если он встречает эту опцию в командной строке, он расширяет вашу строку version (путём замены %prog), выводит её на стандартный вывод и завершает работу.

Например, если ваш скрипт называется /usr/bin/foo:

$ /usr/bin/foo --version
foo 1.0

Следующие два метода можно использовать для печати и получения строки version:

OptionParser.print_version(file=None)

Выводит сообщение о версии для текущей программы (self.version) в file (стандартный вывод по умолчанию). Как и в случае с print_usage(), любое вхождение %prog в self.version заменяется именем текущей программы. Ничего не делает, если self.version пуст или не определён.

OptionParser.get_version()

То же, что и print_version(), но возвращает строку версии вместо её вывода.

Как optparse обрабатывает ошибки?

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

Обработка пользовательских ошибок гораздо важнее, поскольку они гарантированно произойдут независимо от того, насколько стабилен ваш код. optparse может автоматически обнаруживать некоторые пользовательские ошибки, такие как неверные аргументы опции (передача -n 4x, где -n принимает целочисленный аргумент), отсутствующие аргументы (-n в конце командной строки, где -n принимает аргумент любого типа). Кроме того, вы можете вызвать OptionParser.error(), чтобы сообщить об ошибке, определяемой приложением:

(options, args) = parser.parse_args()
...
if options.a and options.b:
    parser.error("options -a and -b are mutually exclusive")

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

Рассмотрим первый пример выше, где пользователь передает 4x опции, принимающая целое число:

$ /usr/bin/foo -n 4x
Usage: foo [options]

foo: error: option -n: invalid integer value: '4x'

Или, когда пользователь вообще не может передать значение:

$ /usr/bin/foo -n
Usage: foo [options]

foo: error: -n option requires an argument

Сгенерированные сообщения об ошибках optparse всегда должны упоминать параметр, связанный с ошибкой; обязательно выполняет то же самое при вызове OptionParser.error() из кода вашего приложения.

Если поведение обработки ошибок по умолчанию optparse не соответствует вашим потребностям, вам потребуется создать подкласс OptionParser и переопределить его методы exit() и/или error().

Собираем все вместе

Вот как обычно выглядят сценарии на основе optparse

from optparse import OptionParser
...
def main():
    usage = "usage: %prog [options] arg"
    parser = OptionParser(usage)
    parser.add_option("-f", "--file", dest="filename",
                      help="read data from FILENAME")
    parser.add_option("-v", "--verbose",
                      action="store_true", dest="verbose")
    parser.add_option("-q", "--quiet",
                      action="store_false", dest="verbose")
    ...
    (options, args) = parser.parse_args()
    if len(args) != 1:
        parser.error("incorrect number of arguments")
    if options.verbose:
        print("reading %s..." % options.filename)
    ...

if __name__ == "__main__":
    main()

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

Создание парсера

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

class optparse.OptionParser(...)

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

usage (по умолчанию: "%prog [options]")
Сводка использования для печати, когда ваша программа запускается неправильно или с опцией помощи. Когда optparse печатает строку использования, она расширяется %prog до os.path.basename(sys.argv[0]) (или до prog, если вы передали данный ключевой аргумент). Чтобы подавить сообщение об использовании, передайте методу специальное значение optparse.SUPPRESS_USAGE.
option_list (по умолчанию: [])
Список объектов Option для заполнения парсера. Опции в option_list добавляются после любых опций в standard_option_list (a атрибут класса, который может быть установлен подклассами 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)
Абзац текста справки для печати после опции help.

Заполнение парсера

Есть несколько способов заполнить парсер параметрами. Предпочтительным способом является использование OptionParser.add_option(), как показано в разделе Учебник по optparse. 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 напрямую.)

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

Каждый экземпляр 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"
сохраняет постоянное значение
"store_true"
сохраняет True
"store_false"
сохраняет 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 — единственный, имеющий смысл для всех опций.

Атрибуты опции

Следующие атрибуты параметров могут быть переданы в качестве ключевых аргументов в 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
Опция.callback_kwargs

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

Option.help

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

Option.metavar

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

Заменяет аргумент(ы) опции для использования при печати текста справки. Пример см. в разделе Учебник по optparse.

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

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

  • "store" [актуально: type, dest, nargs, choices]

    За опцией должен следовать аргумент, преобразуемый в значение в соответствии с type и сохраняется в dest. Если nargs > 1, из командной строки будут использоваться несколько аргументов; все они будут преобразованы в соответствии с type и сохранены в dest в виде кортежа. См. раздел Стандартные типы опций.

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

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

    Если dest не указан, optparse получает пункт назначения из первой длинной строки параметров (например, --foo-bar подразумевает foo_bar). Если длинных строк параметров нет, optparse получает место назначения из первой короткой строки параметров (например, -f подразумевает f).

    Пример:

    parser.add_option("-f")
    parser.add_option("-p", type="float", nargs=3, dest="point")
    

    Как он парсит командную строку:

    -f foo.txt -p 1 -3.5 4 -fbar.txt
    

    optparse установит

    options.f = "foo.txt"
    options.point = (1.0, -3.5, 4.0)
    options.f = "bar.txt"
    
  • "store_const" [требуется: const; актуально: dest]

    Значение const хранится в dest.

    Пример:

    parser.add_option("-q", "--quiet",
                      action="store_const", const=0, dest="verbose")
    parser.add_option("-v", "--verbose",
                      action="store_const", const=1, dest="verbose")
    parser.add_option("--noisy",
                      action="store_const", const=2, dest="verbose")
    

    Если --noisy виден, optparse установит

    options.verbose = 2
    
  • "store_true" [актуально: dest]

    Особый случай "store_const", в котором хранятся значения от True до dest.

  • "store_false" [актуально: dest]

    Как "store_true", но хранит False.

    Пример:

    parser.add_option("--clobber", action="store_true", dest="clobber")
    parser.add_option("--no-clobber", action="store_false", dest="clobber")
    
  • "append" [актуально: type, dest, nargs, choices]

    За опцией должен следовать аргумент, который добавляется к списку в dest. Если значение по умолчанию для dest не указано, автоматически создаётся пустой список, когда optparse впервые встречает данный параметр в командной строке. Если nargs > 1, используется несколько аргументов, и к 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" [требуется: const; актуально: dest]

    Аналогично "store_const", но к dest добавляется значение const; как и в случае с "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 ко всем OptionParsers, поэтому обычно вам не нужно его создавать.

    Пример:

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

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

optparse имеет пять встроенных типов опций: "string", "int", "choice", "float" и "complex". Если вам нужно добавить новые типы опций, см. раздел Расширение optparse.

Аргументы строковых опций никак не проверяются и не преобразуются: текст в командной строке сохраняется в месте назначения (или передаётся обратному вызову) как есть.

Целочисленные аргументы (тип "int") парсится следующим образом:

  • если число начинается с 0x, оно парсится как шестнадцатеричное число.
  • если номер начинается с 0, он парсится как восьмеричное число.
  • если номер начинается с 0b, он парсится как двоичное число.
  • в противном случае число парсится как десятичное число.

Преобразовывает выполняется путём вызова int() с соответствующим основанием (2, 8, 10 или 16). Если это не удастся, то же самое произойдет с optparse, хотя и с более полезным сообщением об ошибке.

Аргументы параметров "float" и "complex" преобразуются напрямую с помощью float() и complex() с аналогичной обработкой ошибок.

Параметры "choice" являются подтипом параметров "string". Атрибут опции choices (последовательность строк) определяет множество допустимых аргументов опции. optparse.check_choice() сравнивает предоставленные пользователем аргументы параметров с этим основным списком и вызывает OptionValueError, если задана недопустимая строка.

Парсинг аргументов

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

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

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

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

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

options
тот же объект, переданный как values, или созданный optparse экземпляр optparse.Values.
args
оставшиеся позиционные аргументы после обработки всех опций

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

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

Запрос и управление вашим парсером опций

Поведение парсера параметров по умолчанию можно немного настроить, и вы также можете покопаться в своём парсере параметров и посмотреть, что там. OptionParser предоставляет несколько помогающих методов:

OptionParser.disable_interspersed_args()

Настраивает парсинг на остановку на первой не-опции. Например, если -a и -b являются простыми параметрами, не принимающими аргументов, optparse обычно принимает данный синтаксис:

prog -a arg1 -b arg2

и рассматривает его как эквивалент

prog -a -b arg1 arg2

Чтобы отключить эту функцию, вызовите по номеру disable_interspersed_args(). Это восстанавливает традиционный синтаксис Unix, где парсинг параметров останавливается с первым аргументом, не являющимся параметром.

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

OptionParser.enable_interspersed_args()

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

OptionParser.get_option(opt_str)

Возвращает экземпляр Option со строкой параметра opt_str или None, если ни один из параметров не имеет строки параметра.

OptionParser.has_option(opt_str)

Возвращает True, если OptionParser имеет опцию со строкой опции opt_str (например, -q или --verbose).

OptionParser.remove_option(opt_str)

Если OptionParser имеет параметр, соответствующий opt_str, данный параметр удаляется. Если данный параметр предоставляет какие-либо другие строки параметров, все данные строки параметров становятся недействительными. Если opt_str не встречается ни в одной опции, принадлежащей этому OptionParser, вызывается ValueError.

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

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

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

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

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

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

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

parser.set_conflict_handler(handler)

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

"error" (по умолчанию)
предположим, что конфликты опций являются ошибкой программирования, и поднимем OptionConflictError
"resolve"
разумно разрешать конфликты опций (см. ниже)

В качестве примера давайте определим OptionParser, интеллектуально разрешающий конфликты, и добавим к нему конфликтующие параметры:

parser = OptionParser(conflict_handler="resolve")
parser.add_option("-n", "--dry-run", ..., help="do no harm")
parser.add_option("-n", "--noisy", ..., help="be noisy")

В данный момент optparse обнаруживает, что ранее добавленная опция уже использует строку опции -n. Поскольку conflict_handler — это "resolve", ситуация решается путём удаления -n из списка строк параметров предыдущего параметра. Теперь --dry-run — единственный способ для пользователя активировать эту опцию. Если пользователь попросит о помощи, справочное сообщение отразит следующее:

Options:
  --dry-run     do no harm
  ...
  -n, --noisy   be noisy

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

parser.add_option("--dry-run", ..., help="new dry-run option")

На данный момент исходная опция -n/--dry-run больше недоступна, поэтому optparse удаляет её, оставляя данный текст справки:

Options:
  ...
  -n, --noisy   be noisy
  --dry-run     new dry-run option

Очистка

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

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

OptionParser поддерживает несколько других общедоступных методов:

OptionParser.set_usage(usage)

Устанавливает строку использования в соответствии с правилами, рассмотренными выше для ключевого аргумента конструктора usage. Передача None устанавливает строку использования по умолчанию; используйте optparse.SUPPRESS_USAGE, чтобы подавить сообщение об использовании.

OptionParser.print_usage(file=None)

Распечатывает сообщение об использовании для текущей программы (self.usage) в file (стандартный вывод по умолчанию). Любое вхождение строки %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")

Опции обратных вызовов

Если встроенных действий и типов optparse недостаточно для ваших нужд, у вас есть два варианта: расширить optparse или определить параметр обратного вызова. Расширение optparse является более общим, но избыточным для многих простых случаев. Довольно часто простой обратный вызов — это все, что вам нужно.

Есть два шага для определения опции обратного вызова:

  • определяет сам параметр с помощью действия "callback".
  • написать обратный вызов; это функция (или метод), принимающая как минимум четыре аргумента, как приведено ниже.

Определение опции обратного вызова

Как всегда, самый простой способ определить параметр обратного вызова — использовать метод OptionParser.add_option(). Помимо action, единственным обязательным атрибутом параметра, является вызываемая функция callback:

parser.add_option("-c", action="callback", callback=my_callback)

callback — это функция (или другой вызываемый объект), поэтому вы должны уже определить my_callback() при создании этой опции обратного вызова. В этом простом случае optparse даже не знает, принимает ли -c какие- либо аргументы, что обычно означает, что опция не принимает аргументов, — простое присутствие -c в командной строке — это все, что ему нужно знать. Однако в некоторых случаях вы можете захотеть, чтобы ваш обратный вызов использовал произвольное количество аргументов командной строки. Здесь написание обратных вызовов становится сложным; это будет рассмотрено позже в этом разделе.

optparse всегда передает четыре конкретных аргумента вашему обратному вызову, и он будет передавать дополнительные аргументы, только если вы укажете их через callback_args и callback_kwargs. Таким образом, минимальная сигнатура функции обратного вызова равна:

def my_callback(option, opt, value, parser):

Четыре аргумента обратного вызова рассмотрены далее.

Существует несколько других атрибутов опции, которые вы можете указать при определении опции обратного вызова:

type
имеет свое обычное значение: как и в случае действий "store" или "append", it указывает optparse использовать один аргумент и преобразовывает его в type. Вместо того, чтобы хранить преобразованные значения в любом месте, тем не менее, optparse передает его вашей функции обратного вызова.
nargs
также имеет свое обычное значение: если он указан и > 1, будет optparse использовать аргументы nargs, каждый из которых должен быть конвертируемым type. Затем он передает кортеж преобразованных значений в ваш колбэк.
callback_args
кортеж дополнительных позиционных аргументов для передачи обратному вызову.
callback_kwargs
словарь дополнительных ключевых аргументов для передачи обратному вызову.

Как вызываются обратные вызовы?

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

func(option, opt_str, value, parser, *args, **kwargs)

где:

option
это экземпляр Option, вызывающий обратный вызов.
opt_str
это строка параметра, видимая в командной строке, которая запускает обратный вызов. (Если использовалась сокращенная длинная опция, opt_str будет полной каноническая строка опции —, например, если пользователь помещает --foo в файл командной строки как аббревиатуру --foobar, тогда будет opt_str "--foobar".).
value
является аргументом этой опции, отображаемой в командной строке. optparse будет ожидать аргумент, только если установлен type; будет тип value тип, подразумеваемый типом опции. Если type для этой опции есть None (аргумент не ожидается), тогда value будет None. Если nargs > 1, value будет кортежем значений соответствующего типа.
parser

является экземпляром OptionParser, управляющим всем этим, в основном полезным, потому что вы можете получить доступ к некоторым другим интересным данным через его атрибуты экземпляра:

parser.largs
текущий список оставшихся аргументов, т.е. израсходованные аргументы, но не являются ни параметрами, ни аргументами параметров. Не стесняйтесь изменять parser.largs, например, добавив к нему дополнительные аргументы. (Данный список будет args, вторым возвращаемым значением parse_args().)
parser.rargs
текущий список оставшихся аргументов, т.е. с opt_str и Удалены value (если применимо) и только аргументы, следующие за ними все ещё там. Не стесняйтесь изменять parser.rargs, например, потребляя больше аргументы.
parser.values
объект, в котором по умолчанию хранятся значения параметров (экземпляр optparse.OptionValues). Это позволяет обратным вызовам использовать тот же механизм, что и метод обратного вызова остальная часть optparse для хранения значений опций; вам не нужно возиться вокруг с глобальными переменными или замыканиями. Вы также можете получить доступ или изменить файл значения любых опций, уже встречавшихся в командной строке.
args
представляет собой кортеж произвольных позиционных аргументов, передаваемых через класс атрибута опции callback_args.
kwargs
представляет собой словарь произвольных ключевых аргументов, поставляемых через callback_kwargs.

Вызов ошибок в обратном вызове

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

Пример обратного вызова 1: тривиальный обратный вызов

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

def record_foo_seen(option, opt_str, value, parser):
    parser.values.saw_foo = True

parser.add_option("--foo", action="callback", callback=record_foo_seen)

Конечно, вы можете сделать это с помощью действия "store_true".

Пример обратного вызова 2: проверка порядка опций

Вот немного более интересный пример: записывает тот факт, что -a виден, но вызывается исключение, если он идет после -b в командной строке.

def check_order(option, opt_str, value, parser):
    if parser.values.b:
        raise OptionValueError("can't use -a after -b")
    parser.values.a = 1
...
parser.add_option("-a", action="callback", callback=check_order)
parser.add_option("-b", action="store_true", dest="b")

Пример обратного вызова 3: проверить порядок опций (обобщенный)

Если вы хотите повторно использовать данный обратный вызов для нескольких похожих опций (установить флаг, но вызвать исключение, если -b уже был замечен), над ним нужно немного поработать: сообщение об ошибке и флаг, который он устанавливает, должны быть обобщены.

def check_order(option, opt_str, value, parser):
    if parser.values.b:
        raise OptionValueError("can't use %s after -b" % opt_str)
    setattr(parser.values, option.dest, 1)
...
parser.add_option("-a", action="callback", callback=check_order, dest='a')
parser.add_option("-b", action="store_true", dest="b")
parser.add_option("-c", action="callback", callback=check_order, dest='c')

Пример обратного вызова 4: проверка произвольного условия

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

def check_moon(option, opt_str, value, parser):
    if is_moon_full():
        raise OptionValueError("%s option invalid when moon is full"
                               % opt_str)
    setattr(parser.values, option.dest, 1)
...
parser.add_option("--foo",
                  action="callback", callback=check_moon, dest="foo")

(Определение is_moon_full() оставлено читателю в качестве упражнения.)

Пример обратного вызова 5: фиксированные аргументы

Все становится немного интереснее, когда вы определяете параметры обратного вызова, принимающие фиксированное количество аргументов. Указание того, что опция обратного вызова принимает аргументы, аналогично определению опции "store" или "append": если вы определяете type, то опция принимает один аргумент, преобразованный в данный тип; если вы дополнительно определите nargs, то опция принимает аргументы nargs.

Вот пример, повторяющий стандартное действие "store":

def store_value(option, opt_str, value, parser):
    setattr(parser.values, option.dest, value)
...
parser.add_option("--foo",
                  action="callback", callback=store_value,
                  type="int", nargs=3, dest="foo")

Обратите внимание, что optparse позаботится о том, чтобы использовать 3 аргумента и преобразовывает их в целые числа для вас; все, что вам нужно сделать, это сохранить их. (Или что-то ещё; очевидно, вам не нужен обратный вызов для этого примера.)

Пример обратного вызова 6: переменные аргументы

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

  • либо --, либо - могут быть аргументами опции.
  • голый -- (если не аргумент какой-либо опции): останавливает обработку командной строки и отбросить --.
  • голый - (если не аргумент какой-либо опции): останавливает обработку командной строки, но сохраняет - (добавить его к parser.largs).

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

Тем не менее, вот попытка обратного вызова для опции с переменными аргументами:

def vararg_callback(option, opt_str, value, parser):
    assert value is None
    value = []

    def floatable(str):
        try:
            float(str)
            return True
        except ValueError:
            return False

    for arg in parser.rargs:
        # остановиться на --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)

Расширение optparse

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

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

Чтобы добавить новые типы, вам нужно определить свой собственный подкласс класса optparse Option. Данный класс имеет пару атрибутов, определяющих типы optparse: TYPES и TYPE_CHECKER.

Option.TYPES

Кортеж имён типов; в своём подклассе просто определяет новый кортеж TYPES, основанный на стандартном.

Option.TYPE_CHECKER

Словарь, отображающий имена типов на функции проверки типов. Функция проверки типов имеет следующую сигнатуру:

def check_mytype(option, opt, value)

где option — экземпляр Option, opt — строка параметра (например, -f), а value — строка из командной строки, которую необходимо проверить и преобразовывает в нужный тип. check_mytype() должен возвращать объект гипотетического типа mytype. Значение, возвращаемое функцией проверки типов, попадет в экземпляр OptionValues, возвращённый OptionParser.parse_args(), или будет передано обратному вызову в качестве параметра value.

Ваша функция проверки типов должна вызывать OptionValueError, если она сталкивается с какими-либо проблемами. OptionValueError принимает один строковый аргумент, передаваемый как есть методу error() OptionParser, который, в свою очередь, добавляет имя программы и строку "error:" и выводит все в stderr перед завершением процесса.

Вот глупый пример, демонстрирующий добавление типа параметра "complex" для парсинга комплексных чисел в стиле Python в командной строке. (Это ещё глупее, чем раньше, потому что в optparse 1.3 добавлена встроенная поддержка комплексных чисел, но это неважно.)

Во-первых, необходимый импорт:

from copy import copy
from optparse import Option, OptionValueError

Сначала вам нужно определить средство проверки типов, т. к. оно упоминается позже (в атрибуте класса TYPE_CHECKER вашего подкласса Option):

def check_complex(option, opt, value):
    try:
        return complex(value)
    except ValueError:
        raise OptionValueError(
            "option %s: invalid complex value: %r" % (opt, value))

Наконец, подкласс Option:

class MyOption (Option):
    TYPES = Option.TYPES + ("complex",)
    TYPE_CHECKER = copy(Option.TYPE_CHECKER)
    TYPE_CHECKER["complex"] = check_complex

(Если бы мы не сделали copy() из Option.TYPE_CHECKER, мы бы в конечном итоге изменили атрибут TYPE_CHECKER класса Option optparse. Поскольку это Python, ничто не мешает вам сделать это, кроме хороших манер и здравого смысла.)

Вот и все! Теперь вы можете написать сценарий, использующий новый тип параметра, как и любой другой сценарий на основе optparse, за исключением того, что вы должны указать OptionParser использовать MyOption вместо Option:

parser = OptionParser(option_class=MyOption)
parser.add_option("-c", type="complex")

В качестве альтернативы вы можете создать свой список опций и передать его в OptionParser; если вы не используете add_option() вышеописанным способом, вам не нужно указывать OptionParser, какой класс параметров использовать:

option_list = [MyOption("-c", action="store", type="complex", dest="c")]
parser = OptionParser(option_list=option_list)

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

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

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