Содержание страницы
36.1. optparse – Парсер параметров командной строки¶optparse – Parser for command line options
Устарело с версии 3.2: Модуль optparse устарел и не будет развиваться; разработка будет продолжена в модуле argparse.
Исходный код: Lib/optparse.py
optparse – более удобная, гибкая и мощная библиотека для разбора параметров командной строки, чем старый модуль getopt. optparse использует более декларативный стиль разбора командной строки: создаётся экземпляр OptionParser, заполняется параметрами и выполняется разбор командной строки. optparse позволяет пользователям задавать параметры в традиционном синтаксисе GNU/POSIX, а также генерирует сообщения об использовании и справку.
Вот пример использования optparse в простом скрипте:
from optparse import OptionParser
[...]
parser = OptionParser()
parser.add_option("-f", "--file", dest="filename",
help="write report to FILE", metavar="FILE")
parser.add_option("-q", "--quiet",
action="store_false", dest="verbose", default=True,
help="don't print status messages to stdout")
(options, args) = parser.parse_args()
С помощью этих нескольких строк кода пользователи вашего скрипта теперь могут делать «обычные вещи» в командной строке, например:
<yourscript> --file=outfile -q
При разборе командной строки optparse устанавливает атрибуты объекта options, возвращаемого parse_args(), на основе значений, указанных пользователем в командной строке. Когда parse_args() завершает разбор этой командной строки, options.filename будет равно "outfile", а options.verbose будет False. optparse поддерживает как длинные, так и короткие опции, позволяет объединять короткие опции вместе и связывать опции с их аргументами различными способами. Таким образом, следующие командные строки эквивалентны приведённому выше примеру:
<yourscript> -f outfile --quiet
<yourscript> --quiet --file outfile
<yourscript> -q -foutfile
<yourscript> -qfoutfile
Кроме того, можно запустить один из
<yourscript> -h
<yourscript> --help
и optparse выведет краткую сводку параметров скрипта:
Usage: <yourscript> [options]
Options:
-h, --help show this help message and exit
-f FILE, --file=FILE write report to FILE
-q, --quiet don't print status messages to stdout
где значение yourscript определяется во время выполнения (обычно из sys.argv[0]).
36.1.1. Предыстория¶Background
optparse был специально спроектирован для поощрения создания программ с простыми и общепринятыми интерфейсами командной строки. Для этого он поддерживает только наиболее распространённый синтаксис и семантику командной строки, традиционно используемые в Unix. Если вы не знакомы с этими соглашениями, прочитайте этот раздел, чтобы ознакомиться с ними.
36.1.1.1. Терминология¶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 и никогда не будут. Это сделано намеренно: первые три нестандартны в любом окружении, а последний имеет смысл только если вы ориентируетесь исключительно на VMS, MS-DOS и/или Windows.
- аргумент опции
аргумент, который следует за опцией, тесно связан с этой опцией и извлекается из списка аргументов вместе с ней. В optparse аргументы опций могут находиться либо в отдельном аргументе от своей опции:
-f foo --file foo
или включены в тот же аргумент:
-ffoo --file=foo
Обычно данная опция либо принимает аргумент, либо нет. Многие хотят функцию «необязательных аргументов опций», означающую, что некоторые опции будут принимать аргумент, если видят его, и не будут, если не видят. Это несколько спорно, поскольку делает разбор неоднозначным: если -a принимает необязательный аргумент, а -b – это совершенно другая опция, как интерпретировать -ab? Из-за этой неоднозначности optparse не поддерживает эту функцию.
- позиционный аргумент
- то, что осталось в списке аргументов после разбора опций, т.е. после того, как опции и их аргументы были разобраны и удалены из списка аргументов.
- обязательная опция
- опция, которая должна быть указана в командной строке; обратите внимание, что фраза «required option» внутренне противоречива в английском языке. optparse не препятствует реализации обязательных опций, но и не оказывает в этом особой помощи.
Например, рассмотрим эту гипотетическую командную строку:
prog -v --report report.txt foo bar
-v и --report – обе опции. Предполагая, что --report принимает один аргумент, report.txt является аргументом опции. foo и bar являются позиционными аргументами.
36.1.1.2. Для чего нужны опции?¶What are options for?
Опции используются для предоставления дополнительной информации для настройки или кастомизации выполнения программы. На всякий случай, если это не было очевидно: опции обычно необязательны. Программа должна нормально работать вообще без опций. (Выберите случайную программу из набора Unix или GNU. Может ли она работать вообще без опций и при этом иметь смысл? Основные исключения – find, tar и dd – все они являются мутантными чудаками, которые справедливо критикуются за нестандартный синтаксис и запутанные интерфейсы.)
Многие хотят, чтобы в их программах были «обязательные опции». Подумайте об этом. Если это обязательно, значит, это не необязательно! Если есть информация, которая absolutely необходима вашей программе для успешного выполнения, для этого существуют позиционные аргументы.
В качестве примера хорошего дизайна интерфейса командной строки рассмотрим скромную утилиту cp для копирования файлов. Не имеет особого смысла пытаться копировать файлы без указания назначения и хотя бы одного источника. Следовательно, cp завершается ошибкой, если запустить её без аргументов. Однако у неё гибкий, полезный синтаксис, который вообще не требует никаких опций:
cp SOURCE DEST
cp SOURCE ... DEST-DIR
С этим можно зайти довольно далеко. Большинство реализаций cp предоставляют множество опций для точной настройки копирования: можно сохранять режим и время изменения, избегать следования симлинкам, спрашивать подтверждение перед перезаписью существующих файлов и т.д. Но ничто из этого не отвлекает от основной миссии cp, которая состоит в копировании одного файла в другой или нескольких файлов в другой каталог.
36.1.1.3. Для чего нужны позиционные аргументы?¶What are positional arguments for?
Позиционные аргументы предназначены для тех частей информации, которые absolutely и однозначно необходимы вашей программе для работы.
Хороший пользовательский интерфейс должен иметь как можно меньше абсолютных требований. Если вашей программе требуется 17 различных частей информации для успешного запуска, не имеет большого значения как вы получаете эту информацию от пользователя – большинство людей сдадутся и уйдут, так и не запустив программу. Это справедливо независимо от того, является ли интерфейс командной строкой, файлом конфигурации или графическим интерфейсом: если вы предъявляете столько требований к пользователям, большинство из них просто сдадутся.
Короче говоря, старайтесь минимизировать объем информации, которую пользователи absolutely обязаны предоставить – используйте разумные значения по умолчанию, когда это возможно. Конечно, вы также хотите сделать свои программы достаточно гибкими. Для этого и нужны опции. Опять же, неважно, являются ли они записями в файле конфигурации, виджетами в диалоге «Настройки» графического интерфейса или опциями командной строки – чем больше опций вы реализуете, тем гибче становится ваша программа, и тем сложнее становится ее реализация. Слишком большая гибкость тоже имеет недостатки; слишком много опций может перегрузить пользователей и сделать ваш код гораздо сложнее в поддержке.
36.1.2. Учебник¶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 (назначение) и help. Из них action является самым основным.
36.1.2.1. Понимание действий опций¶Understanding option actions
Действия сообщают optparse, что делать, когда он встречает опцию в командной строке. Существует фиксированный набор действий, встроенных в optparse; добавление новых действий – продвинутая тема, рассмотренная в разделе Extending optparse. Большинство действий указывают optparse сохранить значение в некоторую переменную – например, взять строку из командной строки и сохранить её в атрибуте options.
Если не указать действие опции, optparse по умолчанию использует store.
36.1.2.2. Действие store¶The 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. Добавление типов рассмотрено в разделе Extending optparse.
36.1.2.3. Обработка логических (флаговых) опций¶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.
36.1.2.4. Другие действия¶Other actions
Некоторые другие действия, поддерживаемые optparse:
- "store_const"
- сохранить константное значение
- "append"
- добавить аргумент этой опции в список
- "count"
- увеличить счётчик на единицу
- "колбэк"
- вызвать указанную функцию
Эти вопросы рассматриваются в разделе Справочное руководство, Справочное руководство и разделе Колбэки опций.
36.1.2.5. Значения по умолчанию¶Default values
Во всех приведённых выше примерах устанавливается некоторая переменная («назначение») при обнаружении определённых опций командной строки. Что произойдёт, если эти опции никогда не будут обнаружены? Поскольку мы не указали никаких значений по умолчанию, все они устанавливаются в None. Обычно это нормально, но иногда требуется больший контроль. optparse позволяет указать значение по умолчанию для каждого назначения, которое присваивается до разбора командной строки.
Сначала рассмотрим пример verbose/quiet. Если мы хотим, чтобы optparse установил verbose в True, если только не встретится -q, то это можно сделать так:
parser.add_option("-v", action="store_true", dest="verbose", default=True)
parser.add_option("-q", action="store_false", dest="verbose")
Поскольку значения по умолчанию применяются к назначению, а не к какому-либо конкретному параметру, и эти два параметра имеют одно и то же назначение, это полностью эквивалентно:
parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose", default=True)
Рассмотрим это:
parser.add_option("-v", action="store_true", dest="verbose", default=False)
parser.add_option("-q", action="store_false", dest="verbose", default=True)
Опять же, значение по умолчанию для verbose будет True: последнее значение по умолчанию, указанное для любого конкретного назначения, считается окончательным.
Более понятный способ указать значения по умолчанию – метод set_defaults() класса OptionParser, который можно вызвать в любое время до вызова parse_args():
parser.set_defaults(verbose=True)
parser.add_option(...)
(options, args) = parser.parse_args()
Как и прежде, последнее указанное значение для данного назначения параметра и будет использоваться. Для ясности старайтесь использовать какой-то один способ задания значений по умолчанию, а не оба сразу.
36.1.2.6. Генерация справки¶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 и неформальным семантическим описанием «write output to FILE». Это простой, но эффективный способ сделать текст справки гораздо понятнее и полезнее для конечных пользователей.
Параметры, имеющие значение по умолчанию, могут включать %default в строку справки – optparse заменит его на str() значения параметра по умолчанию. Если параметр не имеет значения по умолчанию (или значение по умолчанию равно None), %default раскрывается в none.
36.1.2.6.1. Группировка опций¶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.
36.1.2.7. Вывод строки версии¶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(), но возвращает строку версии вместо её вывода.
36.1.2.8. Как 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().
36.1.2.9. Собираем всё вместе¶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()
36.1.3. Справочное руководство¶Reference Guide
36.1.3.1. Создание парсера¶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)
- Абзац текста справки, выводимый после справки по опциям.
36.1.3.2. Заполнение парсера¶Populating the parser
Есть несколько способов наполнить парсер опциями. Предпочтительный – использовать OptionParser.add_option(), как показано в разделе Tutorial. 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 напрямую.)
36.1.3.3. Определение опций¶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"
- сохранить константное значение
- "store_true"
- сохраняет истинное значение
- "store_false"
- сохраняет ложное значение
- "append"
- добавить аргумент этой опции в список
- "append_const"
- добавить константное значение в список
- "count"
- увеличить счётчик на единицу
- \"колбэк\"
- вызвать указанную функцию
- "help"
- вывести сообщение об использовании, включающее все опции и документацию к ним
(Если не указать действие, по умолчанию используется "store". Для этого действия можно также указать атрибуты опции type и dest; см. Standard option actions.)
Как видно, большинство действий сводится к сохранению или обновлению значения где-либо. 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 – единственный, который имеет смысл для всех опций.
36.1.3.4. Атрибуты опций¶Option attributes
Следующие атрибуты опции можно передать как именованные аргументы в 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¶
Для опций с действием "колбэк" – вызываемый объект, который будет вызван при обнаружении этой опции. См. раздел Option Callbacks для получения подробностей об аргументах, передаваемых вызываемому объекту.
- Option.callback_args¶
- Option.callback_kwargs¶
Дополнительные позиционные и именованные аргументы для передачи в колбэк после четырёх стандартных аргументов колбэка.
- Option.help¶
Текст справки для этой опции, выводимый при перечислении всех доступных опций после того, как пользователь укажет опцию help (например, --help). Если текст справки не указан, опция будет перечислена без текста справки. Чтобы скрыть эту опцию, используйте специальное значение optparse.SUPPRESS_HELP.
36.1.3.5. Стандартные действия опций¶Standard option actions
Различные действия опций имеют несколько разные требования и эффекты. У большинства действий есть несколько соответствующих атрибутов опции, которые можно указать, чтобы направлять поведение 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", который сохраняет истинное значение в dest.
"store_false" [относящиеся: dest]
Как "store_true", но сохраняет ложное значение.
Пример:
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", но значение 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
"колбэк" [обязательно: колбэк; относящиеся: type, nargs, callback_args, callback_kwargs]
Вызывает функцию, указанную колбэком колбэк, которая вызывается как
func(option, opt_str, value, parser, *args, **kwargs)
Смотрите раздел Колбэки опций для подробностей.
"help"
Выводит полное справочное сообщение для всех опций текущего анализатора опций. Справочное сообщение строится из строки usage, переданной конструктору OptionParser, и строки help, переданной каждой опции.
Если для опции не указана строка help, она всё равно будет включена в справочное сообщение. Чтобы полностью исключить опцию, используйте специальное значение optparse.SUPPRESS_HELP.
optparse автоматически добавляет опцию help во все анализаторы опций, поэтому обычно не нужно создавать её вручную.
Пример:
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 добавляет их автоматически при необходимости.
36.1.3.6. Стандартные типы опций¶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, если указана недопустимая строка.
36.1.3.7. Разбор аргументов¶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 для ошибок командной строки).
36.1.3.8. Запросы и управление анализатором опций¶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)¶
If the OptionParser has an option corresponding to opt_str, that option is removed. If that option provided any other option strings, all of those option strings become invalid. If opt_str does not occur in any option belonging to this OptionParser, raises ValueError.
36.1.3.9. Конфликты между опциями¶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
36.1.3.10. Очистка¶Cleanup
Экземпляры OptionParser имеют несколько циклических ссылок. Это не должно быть проблемой для сборщика мусора Python, но вы можете захотеть разорвать циклические ссылки явно, вызвав destroy() для вашего OptionParser после завершения работы с ним. Это особенно полезно в долго работающих приложениях, где большие графы объектов достижимы из вашего OptionParser.
36.1.3.11. Другие методы¶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")
36.1.4. Колбэки опций¶Option Callbacks
Когда встроенных действий и типов optparse недостаточно для ваших потребностей, у вас есть два варианта: расширить optparse или определить опцию с колбэком. Расширение optparse более универсально, но избыточно для многих простых случаев. Довольно часто простой колбэк – это всё, что нужно.
Определение опции-колбэка состоит из двух шагов:
- определите саму опцию, используя действие "колбэк"
- написать колбэк – функцию (или метод), которая принимает как минимум четыре аргумента, как описано ниже
36.1.4.1. Определение опции с колбэком¶Defining a callback option
Как всегда, самый простой способ определить опцию с колбэком – использовать метод OptionParser.add_option(). Кроме action, единственным атрибутом опции, который необходимо указать, является колбэк – функция, которую нужно вызвать:
parser.add_option("-c", action="callback", callback=my_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
- словарь дополнительных именованных аргументов, передаваемых колбэку
36.1.4.2. Как вызываются колбэки¶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.
36.1.4.3. Возбуждение ошибок в колбэке¶Raising errors in a callback
Функция обратного вызова должна вызывать OptionValueError, если возникли какие-либо проблемы с опцией или её аргументом(ами). optparse перехватывает это исключение и завершает программу, выводя сообщение об ошибке, которое вы предоставляете, в stderr. Ваше сообщение должно быть ясным, кратким, точным и содержать упоминание опции, вызвавшей ошибку. В противном случае пользователю будет трудно понять, что он сделал неправильно.
36.1.4.4. Пример колбэка 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".
36.1.4.5. Пример колбэка 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")
36.1.4.6. Пример колбэка 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')
36.1.4.7. Пример колбэка 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() оставляется читателю в качестве упражнения.)
36.1.4.8. Пример колбэка 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 аргументов и преобразование их в целые числа; всё, что вам нужно сделать, это сохранить их. (Или что-то ещё; очевидно, что для этого примера колбэк не нужен.)
36.1.4.9. Пример колбэка 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)
36.1.5. Расширение optparse¶Extending optparse
Поскольку двумя основными управляющими факторами того, как optparse интерпретирует параметры командной строки, являются действие и тип каждой опции, наиболее вероятное направление расширения – добавление новых действий и новых типов.
36.1.5.1. Добавление новых типов¶Adding new types
Чтобы добавить новые типы, вам нужно определить свой собственный подкласс класса optparse‘s 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 принимает один строковый аргумент, который передаётся как есть методу OptionParser‘s error(), который, в свою очередь, добавляет имя программы и строку "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 класса optparse‘s Option class. Это же 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)
36.1.5.2. Добавление новых действий¶Adding new actions
Добавление новых действий немного сложнее, потому что нужно понимать, что optparse имеет несколько классификаций действий:
- «store»-действия
- действия, в результате которых optparse сохраняет значение в атрибут текущего экземпляра OptionValues; такие опции требуют передачи атрибута dest конструктору Option.
- «typed»-действия
- действия, которые берут значение из командной строки и ожидают, что оно будет определённого типа; точнее, строка, которую можно преобразовать в определённый тип. Такие опции требуют атрибута type в конструкторе Option.
Это пересекающиеся множества: некоторые действия «store» по умолчанию – "store", "store_const", "append" и "count", в то время как действия «typed» по умолчанию – "store", "append" и "колбэк".
При добавлении действия его нужно отнести к категории, включив как минимум в один из следующих атрибутов класса Option (все они являются списками строк):
- Option.ACTIONS¶
Все действия должны быть перечислены в ACTIONS.
- Option.STORE_ACTIONS¶
«store»-действия дополнительно перечисляются здесь.
- Option.TYPED_ACTIONS¶
«typed»-действия дополнительно перечисляются здесь.
- Option.ALWAYS_TYPED_ACTIONS¶
Действия, которые всегда принимают тип (т.е. их опции всегда принимают значение), дополнительно перечислены здесь. Единственное следствие этого – optparse присваивает тип по умолчанию, "string", опциям без явного типа, чьё действие указано в ALWAYS_TYPED_ACTIONS.
Чтобы реализовать новое действие, необходимо переопределить метод Option take_action() и добавить ветвь, распознающую это действие.
Например, добавим действие "extend". Оно похоже на стандартное действие "append", но вместо того, чтобы брать одно значение из командной строки и добавлять его в конец существующего списка, "extend" принимает несколько значений в одной строке с разделителями-запятыми и расширяет существующий список этими значениями. То есть, если --names – опция "extend" типа "string", то командная строка
--names=foo,bar --names blah --names ding,dong
приведёт к списку
["foo", "bar", "blah", "ding", "dong"]
Снова определим подкласс Option:
class MyOption(Option):
ACTIONS = Option.ACTIONS + ("extend",)
STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",)
def take_action(self, action, dest, opt, value, values, parser):
if action == "extend":
lvalue = value.split(",")
values.ensure_value(dest, []).extend(lvalue)
else:
Option.take_action(
self, action, dest, opt, value, values, parser)
Что следует отметить:
"extend" одновременно ожидает значение в командной строке и сохраняет его, поэтому оно входит как в STORE_ACTIONS, так и в TYPED_ACTIONS.
чтобы гарантировать, что optparse присваивает тип по умолчанию "string" действиям "extend", мы также помещаем действие "extend" в ALWAYS_TYPED_ACTIONS.
MyOption.take_action() реализует только это одно новое действие и возвращает управление Option.take_action() для стандартных действий optparse.
values – экземпляр класса optparse_parser.Values, предоставляющий очень полезный метод ensure_value(). ensure_value() по сути getattr() с предохранительным клапаном; он вызывается как
values.ensure_value(attr, value)
Если атрибут attr объекта values не существует или равен None, то ensure_value() сначала устанавливает его в value, а затем возвращает value. Это очень удобно для таких действий, как "extend", "append" и "count", все они накапливают данные в переменной и ожидают, что эта переменная будет определённого типа (список для первых двух, целое число – для последнего). Использование ensure_value() означает, что скриптам, использующим ваше действие, не нужно беспокоиться об установке значения по умолчанию для соответствующих целевых опций; они могут просто оставить значение по умолчанию как None, и ensure_value() позаботится о правильной установке, когда это понадобится.