optparse
— Парсер для опций командной строки¶
Источник: Lib/optparse.py
Не рекомендуется, начиная с версии 3.2: Модуль optparse
является soft deprecated и не будет развиваться дальше; разработка будет продолжена для модуля 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
и никогда не будут поддерживаться. Это сделано намеренно: первые три нестандартны для любой среды, а последний имеет смысл только в том случае, если вы ориентируетесь исключительно на Windows или некоторые устаревшие платформы (например, VMS, MS-DOS).- аргумент опции
аргумент, который следует за опцией, тесно связан с ней и потребляется из списка аргументов при выполнении этой опции. При использовании
optparse
аргументы опции могут находиться в отдельном аргументе от опции:-f foo --file foo
или включены в один аргумент:
-ffoo --file=foo
Обычно опция либо принимает аргумент, либо нет. Многие хотят иметь функцию «необязательных аргументов опции», то есть некоторые опции будут принимать аргумент, если видят его, и не будут, если не видят. Это несколько спорно, потому что делает разбор неоднозначным: если
-a
принимает необязательный аргумент, а-b
- это совсем другая опция, как нам интерпретировать-ab
? Из-за этой неоднозначностиoptparse
не поддерживает эту возможность.- позиционный аргумент
то, что осталось в списке аргументов после разбора опций, т.е. после того, как опции и их аргументы были разобраны и удалены из списка аргументов.
- необходимая опция
опция, которая должна быть указана в командной строке; обратите внимание, что фраза «обязательная опция» в английском языке является самопротиворечивой.
optparse
не мешает вам реализовать обязательные опции, но и не сильно помогает в этом.
Например, рассмотрим гипотетическую командную строку:
prog -v --report report.txt foo bar
-v
и --report
являются опциями. Если предположить, что --report
принимает один аргумент, то report.txt
является аргументом опции. foo
и bar
- позиционные аргументы.
Для чего нужны опционы?¶
Опции используются для предоставления дополнительной информации, чтобы настроить выполнение программы. Если вы не поняли, опции обычно являются опциональными. Программа должна прекрасно работать без каких-либо опций. (Выберите произвольную программу из набора инструментов Unix или GNU. Может ли она работать вообще без каких-либо опций и сохранять смысл? Основными исключениями являются find
, tar
и dd
- все они являются мутантами-чудаками, которые справедливо критикуются за нестандартный синтаксис и запутанный интерфейс.)
Многие люди хотят, чтобы в их программах были «обязательные опции». Подумайте об этом. Если опция обязательна, то она не необязательна! Если есть часть информации, которая абсолютно необходима вашей программе для успешного выполнения, то для этого и нужны позиционные аргументы.
В качестве примера хорошего дизайна интерфейса командной строки рассмотрим скромную утилиту cp
, предназначенную для копирования файлов. Не имеет смысла пытаться копировать файлы, не указав пункт назначения и хотя бы один источник. Поэтому cp
не работает, если запустить ее без аргументов. Однако у нее есть гибкий и полезный синтаксис, который не требует никаких опций:
cp SOURCE DEST
cp SOURCE ... DEST-DIR
На этом можно далеко продвинуться. Большинство реализаций cp
предоставляют кучу опций для настройки того, как именно копируются файлы: вы можете сохранить режим и время модификации, избегать следования по симлинкам, спрашивать, прежде чем уничтожать существующие файлы, и т. д. Но все это не отвлекает от основной задачи cp
, которая заключается в копировании либо одного файла в другой, либо нескольких файлов в другой каталог.
Для чего нужны позиционные аргументы?¶
Позиционные аргументы предназначены для тех фрагментов информации, которые совершенно точно и безоговорочно необходимы вашей программе для выполнения.
Хороший пользовательский интерфейс должен иметь как можно меньше абсолютных требований. Если для успешной работы вашей программы требуется 17 различных частей информации, не имеет особого значения, каким образом вы получите эту информацию от пользователя - большинство людей сдадутся и уйдут, прежде чем успешно запустят программу. Это касается и командной строки, и файла конфигурации, и графического интерфейса: если вы предъявляете к пользователям столько требований, большинство из них просто сдадутся.
Короче говоря, постарайтесь свести к минимуму количество информации, которую пользователь должен предоставлять в обязательном порядке - используйте разумные значения по умолчанию, когда это возможно. Конечно, вы также хотите сделать свои программы достаточно гибкими. Для этого и нужны опции. Опять же, неважно, будут ли это записи в конфигурационном файле, виджеты в диалоге «Параметры» графического интерфейса или опции командной строки - чем больше опций вы реализуете, тем более гибкой становится ваша программа и тем сложнее ее реализация. Разумеется, у излишней гибкости есть и недостатки: слишком большое количество опций может перегрузить пользователей и сделать ваш код гораздо более сложным для сопровождения.
Учебное пособие¶
Хотя optparse
является довольно гибким и мощным, в большинстве случаев он также прост в использовании. В этом разделе рассматриваются шаблоны кода, характерные для любой optparse
-базированной программы.
Сначала нужно импортировать класс OptionParser, а затем в начале основной программы создать экземпляр OptionParser:
from optparse import OptionParser
...
parser = OptionParser()
Затем можно приступить к определению опций. Основной синтаксис:
parser.add_option(opt_str, ...,
attr=value, ...)
Каждая опция имеет одну или несколько строк, например -f
или --file
, и несколько атрибутов опции, которые указывают optparse
, что ожидать и что делать, когда она встречает эту опцию в командной строке.
Как правило, каждый вариант имеет одну короткую и одну длинную строки, например:
parser.add_option("-f", "--file", ...)
Вы можете определить столько коротких и столько длинных опционных строк, сколько захотите (включая ноль), пока в целом существует хотя бы одна опционная строка.
Строки опций, переданные в OptionParser.add_option()
, фактически являются метками для опций, определенных этим вызовом. Для краткости мы будем часто ссылаться на встречу опции в командной строке; в действительности optparse
встречает строки опций и ищет опции из них.
Когда все параметры определены, поручите optparse
разобрать командную строку вашей программы:
(options, args) = parser.parse_args()
(При желании вы можете передать в parse_args()
собственный список аргументов, но это редко бывает необходимо: по умолчанию используется sys.argv[1:]
).
parse_args()
возвращает два значения:
options
, объект, содержащий значения для всех ваших опций - например, если--file
принимает единственный строковый аргумент, тоoptions.file
будет именем файла, предоставленным пользователем, илиNone
, если пользователь не предоставил эту опциюargs
, список позиционных аргументов, оставшихся после разбора опций
В этом учебном разделе рассматриваются только четыре наиболее важных атрибута опций: action
, type
, dest
(назначение) и help
. Из них action
является наиболее фундаментальным.
Понимание действия опционов¶
Действия указывают optparse
, что делать, когда он встречает опцию в командной строке. Существует фиксированный набор действий, жестко закодированный в optparse
; добавление новых действий - это расширенная тема, рассматриваемая в разделе Расширение optparse. Большинство действий указывают optparse
сохранить значение в некоторой переменной - например, взять строку из командной строки и сохранить ее в атрибуте options
.
Если вы не указали действие опции, то по умолчанию optparse
принимает значение store
.
Действие магазина¶
Наиболее распространенным действием опции является store
, которая указывает optparse
принять следующий аргумент (или остаток текущего аргумента), убедиться, что он имеет правильный тип, и сохранить его в выбранном вами месте назначения.
Например:
parser.add_option("-f", "--file",
action="store", type="string", dest="filename")
Теперь давайте создадим фальшивую командную строку и попросим optparse
разобрать ее:
args = ["-f", "foo.txt"]
(options, args) = parser.parse_args(args)
Когда optparse
видит строку опций -f
, он потребляет следующий аргумент, foo.txt
, и сохраняет его в options.filename
. Таким образом, после этого вызова parse_args()
options.filename
становится "foo.txt"
.
Некоторые другие типы опций, поддерживаемые optparse
, - это int
и float
. Вот опция, которая ожидает целочисленный аргумент:
parser.add_option("-n", type="int", dest="num")
Обратите внимание, что эта опция не имеет длинной строки опций, что вполне допустимо. Также нет явного действия, поскольку по умолчанию используется store
.
Давайте разберем еще одну поддельную командную строку. На этот раз мы поместим аргумент опции прямо против опции: поскольку -n42
(один аргумент) эквивалентен -n 42
(два аргумента), код
(options, args) = parser.parse_args(["-n42"])
print(options.num)
выведет 42
.
Если вы не указываете тип, то optparse
предполагает string
. В сочетании с тем фактом, что действие по умолчанию - store
, это означает, что наш первый пример может быть намного короче:
parser.add_option("-f", "--file", dest="filename")
Если вы не указали пункт назначения, optparse
вычисляет разумное значение по умолчанию из строк опций: если первая длинная строка опций - --foo-bar
, то пункт назначения по умолчанию - foo_bar
. Если длинных строк опций нет, optparse
обращается к первой короткой строке опций: пункт назначения по умолчанию для -f
будет f
.
optparse
также включает встроенный тип complex
. Добавление типов рассматривается в разделе Расширение optparse.
Обработка булевых (флаговых) опций¶
Флажковые опции - установка переменной в true или false при появлении определенной опции - встречаются довольно часто. optparse
поддерживает их с помощью двух отдельных действий, store_true
и store_false
. Например, у вас может быть флаг verbose
, который включается с помощью -v
и выключается с помощью -q
:
parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose")
Здесь у нас два разных варианта с одинаковым назначением, что совершенно нормально. (Это просто означает, что нужно быть немного осторожным при установке значений по умолчанию - см. ниже).
Когда optparse
встречает -v
в командной строке, он устанавливает options.verbose
в True
; когда он встречает -q
, options.verbose
устанавливается в False
.
Другие действия¶
Некоторые другие действия, поддерживаемые optparse
:
"store_const"
хранить постоянное значение, предварительно установленное через
Option.const
."append"
добавить аргумент этой опции в список
"count"
увеличить счетчик на единицу
"callback"
вызов указанной функции
Эти вопросы рассматриваются в разделе Справочное руководство и разделе Обратные вызовы опций.
Значения по умолчанию¶
Все приведенные выше примеры подразумевают установку некоторой переменной («назначения») при появлении определенных опций командной строки. Что произойдет, если эти параметры никогда не будут видны? Поскольку мы не задали никаких значений по умолчанию, все они будут установлены в None
. Обычно это нормально, но иногда хочется большего контроля. optparse
позволяет задать значение по умолчанию для каждого пункта назначения, которое присваивается до разбора командной строки.
Сначала рассмотрим пример verbose/quiet. Если мы хотим, чтобы optparse
устанавливал verbose
в True
, пока не появится -q
, то мы можем сделать следующее:
parser.add_option("-v", action="store_true", dest="verbose", default=True)
parser.add_option("-q", action="store_false", dest="verbose")
Поскольку значения по умолчанию применяются к назначению, а не к какому-либо конкретному параметру, а эти два параметра имеют одно и то же назначение, это абсолютно эквивалентно:
parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose", default=True)
Подумайте вот о чем:
parser.add_option("-v", action="store_true", dest="verbose", default=False)
parser.add_option("-q", action="store_false", dest="verbose", default=True)
Опять же, значением по умолчанию для verbose
будет True
: последнее значение по умолчанию, предоставленное для любого конкретного пункта назначения, является тем, которое имеет значение.
Более понятным способом указания значений по умолчанию является метод set_defaults()
OptionParser, который можно вызвать в любой момент перед вызовом parse_args()
:
parser.set_defaults(verbose=True)
parser.add_option(...)
(options, args) = parser.parse_args()
Как и раньше, последнее значение, указанное для данного пункта назначения опций, имеет значение. Для ясности старайтесь использовать тот или иной метод установки значений по умолчанию, а не оба.
Генерация помощи¶
Способность optparse
автоматически генерировать справку и текст об использовании полезна для создания удобных интерфейсов командной строки. Все, что вам нужно сделать, это указать значение help
для каждой опции и, по желанию, краткое сообщение об использовании всей вашей программы. Вот OptionParser, заполненный удобными для пользователя (документированными) опциями:
usage = "usage: %prog [options] arg1 arg2"
parser = OptionParser(usage=usage)
parser.add_option("-v", "--verbose",
action="store_true", dest="verbose", default=True,
help="make lots of noise [default]")
parser.add_option("-q", "--quiet",
action="store_false", dest="verbose",
help="be vewwy quiet (I'm hunting wabbits)")
parser.add_option("-f", "--filename",
metavar="FILE", help="write output to FILE")
parser.add_option("-m", "--mode",
default="intermediate",
help="interaction mode: novice, intermediate, "
"or expert [default: %default]")
Если optparse
встречает в командной строке -h
или --help
, или если вы просто вызываете parser.print_help()
, он выводит на стандартный вывод следующее:
Usage: <yourscript> [options] arg1 arg2
Options:
-h, --help show this help message and exit
-v, --verbose make lots of noise [default]
-q, --quiet be vewwy quiet (I'm hunting wabbits)
-f FILE, --filename=FILE
write output to FILE
-m MODE, --mode=MODE interaction mode: novice, intermediate, or
expert [default: intermediate]
(Если вывод справки вызван опцией справки, optparse
завершается после печати текста справки).
Здесь многое сделано для того, чтобы помочь optparse
сгенерировать лучшее из возможных сообщений о помощи:
скрипт определяет свое собственное сообщение об использовании:
usage = "usage: %prog [options] arg1 arg2"
optparse
расширяет%prog
в строке использования до имени текущей программы, т.е.os.path.basename(sys.argv[0])
. Расширенная строка выводится перед подробной справкой по опциям.Если вы не укажете строку использования,
optparse
будет использовать скромное, но разумное значение по умолчанию:"Usage: %prog [options]"
, что хорошо, если ваш скрипт не принимает никаких позиционных аргументов.Каждая опция определяет строку справки и не заботится об обертывании строк -
optparse
позаботится об обертывании строк и приведении справки в надлежащий вид.Опции, принимающие значение, указывают на это в автоматически создаваемом справочном сообщении, например, для опции «mode»:
-m MODE, --mode=MODE
Здесь «MODE» называется метапеременной: она обозначает аргумент, который пользователь должен передать в
-m
/--mode
. По умолчаниюoptparse
преобразует имя целевой переменной в верхний регистр и использует его для мета-переменной. Иногда это не то, что вам нужно - например, опция--filename
явно задаетmetavar="FILE"
, в результате чего автоматически генерируется такое описание опции:-f FILE, --filename=FILE
Однако это важно не только для экономии места: в написанном вручную тексте справки используется метапеременная
FILE
, чтобы подсказать пользователю, что существует связь между полуформальным синтаксисом-f FILE
и неформальным семантическим описанием «записать вывод в FILE». Это простой, но эффективный способ сделать текст справки намного понятнее и полезнее для конечных пользователей.Опции, имеющие значение по умолчанию, могут включать
%default
в строку справки—optparse
заменит его наstr()
значения опции по умолчанию. Если опция не имеет значения по умолчанию (или значение по умолчанию равноNone
),%default
расширяется доnone
.
Параметры группировки¶
При работе с большим количеством опций удобно группировать их для более удобного вывода справки. Группа OptionParser
может содержать несколько групп опций, каждая из которых может содержать несколько опций.
Группа опционов получается с помощью класса OptionGroup
:
- class optparse.OptionGroup(parser, title, description=None)¶
где
парсер - это экземпляр
OptionParser
, в который будет вставлена группаtitle - название группы
описание, необязательно, длинное описание группы
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
), печатает ее в stdout и выходит из программы.
Например, если ваш скрипт называется /usr/bin/foo
:
$ /usr/bin/foo --version
foo 1.0
Следующие два метода можно использовать для печати и получения строки version
:
- OptionParser.print_version(file=None)¶
Печать сообщения о версии текущей программы (
self.version
) в файл (по умолчанию stdout). Как и в случае с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
(атрибут класса, который может быть установлен подклассами OptionParser), но перед любыми опциями версии или справки. Утратил силу; вместо него используйтеadd_option()
после создания парсера.option_class
(по умолчанию: optparse.Option)Класс для использования при добавлении опций к парсеру в
add_option()
.version
(по умолчанию:None
)Строка версии для печати, когда пользователь указывает опцию версии. Если для
version
указано значение true, тоoptparse
автоматически добавляет вариант версии с единственной строкой--version
. Подстрока%prog
расширяется так же, как и дляusage
.conflict_handler
(по умолчанию:"error"
)Указывает, что делать, когда в парсер добавляются опции с конфликтующими строками опций; см. раздел Противоречия между вариантами.
description
(по умолчанию:None
)Абзац текста, дающий краткий обзор вашей программы.
optparse
переформатирует этот абзац под текущую ширину терминала и печатает его, когда пользователь запрашивает помощь (послеusage
, но перед списком опций).formatter
(по умолчанию: новыйIndentedHelpFormatter
)Экземпляр optparse.HelpFormatter, который будет использоваться для печати текста справки.
optparse
предоставляет два конкретных класса для этой цели: IndentedHelpFormatter и TitledHelpFormatter.add_help_option
(по умолчанию:True
)Если значение true, то
optparse
добавит в парсер опцию помощи (со строками опций-h
и--help
).prog
Строка, которую следует использовать при расширении
%prog
вusage
иversion
вместоos.path.basename(sys.argv[0])
.epilog
(по умолчанию:None
)Параграф текста справки, который нужно напечатать после опции help.
Наполнение парсера¶
Существует несколько способов заполнения парсера опциями. Предпочтительным является использование OptionParser.add_option()
, как показано в разделе Учебное пособие. add_option()
может быть вызван одним из двух способов:
передайте ему экземпляр Option (как возвращено
make_option()
)Передайте ему любую комбинацию позиционных и ключевых аргументов, приемлемых для
make_option()
(т.е. для конструктора Option), и он создаст для вас экземпляр Option
Другая альтернатива - передать конструктору OptionParser список предварительно сконструированных экземпляров Option, как в:
option_list = [
make_option("-f", "--filename",
action="store", type="string", dest="filename"),
make_option("-q", "--quiet",
action="store_false", dest="verbose"),
]
parser = OptionParser(option_list=option_list)
(make_option()
- это фабричная функция для создания экземпляров Option; в настоящее время она является псевдонимом конструктора Option. Будущая версия optparse
может разделить Option на несколько классов, и make_option()
будет выбирать нужный класс для инстанцирования. Не инстанцируйте Option напрямую).
Определение опций¶
Каждый экземпляр Option представляет собой набор синонимичных строк опций командной строки, например -f
и --file
. Вы можете указать любое количество коротких или длинных строк опций, но вы должны указать хотя бы одну общую строку опций.
Канонический способ создания экземпляра Option
- это метод add_option()
из OptionParser
.
- OptionParser.add_option(option)¶
- OptionParser.add_option(*opt_str, attr=value, ...)
Чтобы задать опцию с помощью только короткой строки:
parser.add_option("-f", attr=value, ...)
А для определения опции достаточно длинной строки опции:
parser.add_option("--foo", attr=value, ...)
Аргументы ключевого слова определяют атрибуты нового объекта Option. Наиболее важным атрибутом опции является
action
, и он в значительной степени определяет, какие другие атрибуты являются релевантными или обязательными. Если вы передадите неактуальные атрибуты опции или не передадите необходимые,optparse
вызовет исключениеOptionError
, объясняющее вашу ошибку.Действие опции определяет, что делает
optparse
, когда встречает эту опцию в командной строке. Стандартными действиями опции, жестко закодированными вoptparse
, являются:"store"
хранить аргумент этой опции (по умолчанию)
"store_const"
хранить постоянное значение, предварительно установленное через
Option.const
."store_true"
магазин
True
"store_false"
магазин
False
"append"
добавить аргумент этой опции в список
"append_const"
добавить константное значение в список, предварительно заданное через
Option.const
."count"
увеличить счетчик на единицу
"callback"
вызов указанной функции
"help"
вывести сообщение об использовании, включающее все опции и документацию по ним
(Если вы не указали действие, по умолчанию используется
"store"
. Для этого действия можно также указать атрибутыtype
иdest
; см. Стандартные действия с опциями).
Как видите, большинство действий связано с сохранением или обновлением какого-либо значения. optparse
всегда создает для этого специальный объект, условно называемый options
, который является экземпляром optparse.Values
.
- class optparse.Values¶
Объект, содержащий разобранные имена аргументов и значения в качестве атрибутов. Обычно создается вызовом при обращении к
OptionParser.parse_args()
, и может быть переопределен пользовательским подклассом, переданным в аргумент values вOptionParser.parse_args()
(как описано в Разбор аргументов).
Аргументы опций (и различные другие значения) хранятся как атрибуты этого объекта в соответствии с атрибутом опции dest
(назначение).
Например, когда вы вызываете
parser.parse_args()
Одним из первых действий optparse
является создание объекта options
:
options = Values()
Если одна из опций этого парсера определена с помощью
parser.add_option("-f", "--file", action="store", type="string", dest="filename")
и разбираемая командная строка содержит любой из следующих элементов:
-ffoo
-f foo
--file=foo
--file foo
то optparse
, увидев эту опцию, сделает эквивалент
options.filename = "foo"
Атрибуты опций type
и dest
почти так же важны, как и action
, но action
- единственный, который имеет смысл для всех опций.
Атрибуты опций¶
- class optparse.Option¶
Единственный аргумент командной строки, различные атрибуты которого передаются в конструктор по ключевому слову. Обычно создается с помощью
OptionParser.add_option()
, а не напрямую, и может быть переопределена пользовательским классом с помощью аргумента option_class вOptionParser
.
Следующие атрибуты опций могут быть переданы в качестве аргументов ключевого слова в OptionParser.add_option()
. Если вы передадите атрибут опции, который не относится к конкретной опции, или не передадите обязательный атрибут опции, optparse
вызовет ошибку OptionError
.
- Option.action¶
(по умолчанию:
"store"
)Определяет поведение
optparse
, когда эта опция встречается в командной строке; доступные опции документированы here.
- Option.type¶
(по умолчанию:
"string"
)Тип аргумента, ожидаемый этой опцией (например,
"string"
или"int"
); доступные типы опций документированы here.
- Option.dest¶
(по умолчанию: извлекается из строк опций)
Если действие опции подразумевает запись или изменение значения в каком-либо месте, это указывает
optparse
, куда его записать:dest
называет атрибут объектаoptions
, которыйoptparse
строит при разборе командной строки.
- Option.default¶
Значение, которое следует использовать для назначения этой опции, если опция не видна в командной строке. См. также
OptionParser.set_defaults()
.
- Option.nargs¶
(по умолчанию: 1)
Сколько аргументов типа
type
должно быть использовано при появлении этой опции. Если > 1, тоoptparse
будет сохранять кортеж значений вdest
.
- Option.const¶
Для действий, сохраняющих постоянное значение, - постоянное значение, которое нужно сохранить.
- Option.choices¶
Для опций типа
"choice"
- список строк, из которых пользователь может выбирать.
- Option.callback¶
Для опций с действием
"callback"
- вызываемая переменная, которую нужно вызвать при появлении этой опции. Подробнее об аргументах, передаваемых вызываемому файлу, см. в разделе Обратные вызовы опций.
- Option.callback_args¶
- Option.callback_kwargs¶
Дополнительные позиционные и ключевые аргументы для передачи в
callback
после четырех стандартных аргументов обратного вызова.
- Option.help¶
Текст справки для этого параметра при выводе списка всех доступных параметров после ввода пользователем параметра
help
(например,--help
). Если текст справки не указан, опция будет выведена без текста справки. Чтобы скрыть этот параметр, используйте специальное значениеoptparse.SUPPRESS_HELP
.
- Option.metavar¶
(по умолчанию: извлекается из строк опций)
Запасной вариант аргумента(ов) опции, который(ые) следует использовать при печати текста справки. Пример см. в разделе Учебное пособие.
Стандартные действия с опциями¶
Различные действия с опциями имеют несколько разные требования и эффекты. Большинство действий имеют несколько соответствующих атрибутов опции, которые вы можете указать, чтобы направить поведение optparse
; некоторые имеют обязательные атрибуты, которые вы должны указать для любой опции, использующей это действие.
"store"
[актуально:type
,dest
,nargs
,choices
]За опцией должен следовать аргумент, который преобразуется в значение в соответствии с
type
и сохраняется вdest
. Еслиnargs
> 1, из командной строки будет получено несколько аргументов; все они будут преобразованы в соответствии сtype
и сохранены вdest
в виде кортежа. См. раздел Стандартные типы опций.Если указан
choices
(список или кортеж строк), тип по умолчанию принимает значение"choice"
.Если значение
type
не указано, по умолчанию используется значение"string"
.Если значение
dest
не указано,optparse
определяет пункт назначения из первой длинной строки опций (например,--foo-bar
подразумеваетfoo_bar
). Если длинных строк опций нет,optparse
определяет пункт назначения из первой короткой строки опций (например,-f
подразумеваетf
).Пример:
parser.add_option("-f") parser.add_option("-p", type="float", nargs=3, dest="point")
При разборе командной строки
-f foo.txt -p 1 -3.5 4 -fbar.txt
optparse
будет установленoptions.f = "foo.txt" options.point = (1.0, -3.5, 4.0) options.f = "bar.txt"
"store_const"
[требуется:const
; актуально:dest
]Значение
const
сохраняется вdest
.Пример:
parser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbose") parser.add_option("-v", "--verbose", action="store_const", const=1, dest="verbose") parser.add_option("--noisy", action="store_const", const=2, dest="verbose")
Если виден
--noisy
, тоoptparse
установитoptions.verbose = 2
"store_true"
[актуально:dest
]Частный случай
"store_const"
, который сохраняетTrue
доdest
."store_false"
[актуально:dest
]Как
"store_true"
, но хранитFalse
.Пример:
parser.add_option("--clobber", action="store_true", dest="clobber") parser.add_option("--no-clobber", action="store_false", dest="clobber")
"append"
[актуально:type
,dest
,nargs
,choices
]За опцией должен следовать аргумент, который добавляется к списку в
dest
. Если значение по умолчанию дляdest
не задано, то при первой встречеoptparse
с этой опцией в командной строке автоматически создается пустой список. Еслиnargs
> 1, то используется несколько аргументов, и к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
"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 # usually, a help option is added automatically, but that can # be suppressed using the add_help_option argument parser = OptionParser(add_help_option=False) parser.add_option("-h", "--help", action="help") parser.add_option("-v", action="store_true", dest="verbose", help="Be moderately verbose") parser.add_option("--file", dest="filename", help="Input file to read data from") parser.add_option("--secret", help=SUPPRESS_HELP)
Если
optparse
видит в командной строке-h
или--help
, он выведет в stdout что-то вроде следующего справочного сообщения (при условии, чтоsys.argv[0]
- это"foo.py"
):Usage: foo.py [options] Options: -h, --help Show this help message and exit -v Be moderately verbose --file=FILENAME Input file to read data from
После печати справочного сообщения
optparse
завершает ваш процесс с помощьюsys.exit(0)
."version"
Выводит номер версии, переданный OptionParser, в stdout и завершает работу. Номер версии на самом деле форматируется и выводится методом
print_version()
OptionParser. Обычно имеет значение только в том случае, если в конструкторе OptionParser указан аргументversion
. Как и в случае с опциямиhelp
, вы редко будете создавать опцииversion
, посколькуoptparse
автоматически добавляет их, когда это необходимо.
Стандартные типы опций¶
optparse
имеет пять встроенных типов опций: "string"
, "int"
, "choice"
, "float"
и "complex"
. Если вам нужно добавить новые типы опций, см. раздел Расширение optparse.
Аргументы строковых опций никак не проверяются и не преобразуются: текст командной строки сохраняется в месте назначения (или передается в обратный вызов) как есть.
Целочисленные аргументы (тип "int"
) разбираются следующим образом:
если число начинается с
0x
, оно будет разобрано как шестнадцатеричное числоесли число начинается с
0
, то оно будет разобрано как восьмеричное числоесли число начинается с
0b
, то оно будет разобрано как двоичное числов противном случае число будет обработано как десятичное.
Преобразование выполняется вызовом int()
с соответствующим основанием (2, 8, 10 или 16). Если это не удается, вызов optparse
тоже будет выполнен, но с более полезным сообщением об ошибке.
Опциональные аргументы "float"
и "complex"
преобразуются непосредственно с помощью float()
и complex()
, с аналогичной обработкой ошибок.
Опции "choice"
являются подтипом опций "string"
. Атрибут choices
опции (последовательность строк) определяет набор допустимых аргументов опции. optparse.check_choice()
сравнивает аргументы опций, предоставленные пользователем, с этим основным списком и выдает сообщение OptionValueError
, если указана недопустимая строка.
Разбор аргументов¶
Весь смысл создания и наполнения OptionParser заключается в вызове его метода parse_args()
.
- OptionParser.parse_args(args=None, values=None)¶
Разбор параметров командной строки, содержащихся в args.
Входными параметрами являются
args
список аргументов для обработки (по умолчанию:
sys.argv[1:]
)values
объект
Values
для хранения аргументов опции (по умолчанию: новый экземплярValues
) - если вы передадите существующий объект, параметры опции по умолчанию не будут инициализированы на нем
а возвращаемое значение - пара
(options, args)
, гдеoptions
тот же объект, который был передан в качестве значения, или экземпляр
optparse.Values
, созданныйoptparse
.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
) в файл (по умолчанию stdout). Любое вхождение строки%prog
вself.usage
заменяется именем текущей программы. Ничего не делает, еслиself.usage
пуст или не определен.
- OptionParser.get_usage()¶
Аналогично
print_usage()
, но вместо печати возвращает строку использования.
- OptionParser.set_defaults(dest=value, ...)¶
Установите значения по умолчанию сразу для нескольких пунктов назначения опций. Использование
set_defaults()
является предпочтительным способом установки значений по умолчанию для опций, поскольку несколько опций могут использовать одно и то же место назначения. Например, если несколько опций «mode» задают один и тот же пункт назначения, любая из них может установить значение по умолчанию, и победит последняя:parser.add_option("--advanced", action="store_const", dest="mode", const="advanced", default="novice") # overridden below parser.add_option("--novice", action="store_const", dest="mode", const="novice", default="advanced") # overrides above setting
Чтобы избежать этой путаницы, используйте
set_defaults()
:parser.set_defaults(mode="advanced") parser.add_option("--advanced", action="store_const", dest="mode", const="advanced") parser.add_option("--novice", action="store_const", dest="mode", const="novice")
Обратные вызовы опций¶
Если встроенных действий и типов optparse
недостаточно для ваших нужд, у вас есть два варианта: расширить optparse
или определить опцию обратного вызова. Расширение optparse
является более общим, но излишним для многих простых случаев. Довольно часто достаточно простого обратного вызова.
Определение опции обратного вызова состоит из двух этапов:
определите саму опцию с помощью действия
"callback"
.напишите обратный вызов; это функция (или метод), принимающая не менее четырех аргументов, как описано ниже
Определение опции обратного вызова¶
Как всегда, самый простой способ определить опцию обратного вызова - это использовать метод OptionParser.add_option()
. Кроме action
, единственным атрибутом опции, который вы должны указать, является callback
, функция для вызова:
parser.add_option("-c", action="callback", callback=my_callback)
callback
- это функция (или другой вызываемый объект), поэтому вы должны были уже определить my_callback()
при создании этой опции обратного вызова. В этом простом случае optparse
даже не знает, принимает ли -c
какие-либо аргументы, что обычно означает, что опция не принимает никаких аргументов - простое присутствие -c
в командной строке - это все, что ей нужно знать. Однако в некоторых обстоятельствах вы можете захотеть, чтобы обратный вызов принимал произвольное количество аргументов командной строки. Именно в этом случае написание обратных вызовов становится сложной задачей, о которой мы расскажем далее в этом разделе.
optparse
всегда передает четыре определенных аргумента обратному вызову, а дополнительные аргументы будут переданы только в том случае, если вы укажете их через callback_args
и callback_kwargs
. Таким образом, минимальная сигнатура функции обратного вызова выглядит так:
def my_callback(option, opt, value, parser):
Четыре аргумента обратного вызова описаны ниже.
Существует несколько других атрибутов опции, которые вы можете указать при определении опции обратного вызова:
type
имеет обычное значение: как и в случае с действиями
"store"
или"append"
, он указываетoptparse
на потребление одного аргумента и его преобразование вtype
. Однако вместо того, чтобы хранить преобразованное значение (значения) где-либо,optparse
передает его в вашу функцию обратного вызова.nargs
также имеет свое обычное значение: если оно задано и > 1,
optparse
будет потреблятьnargs
аргументов, каждый из которых должен быть преобразован вtype
. Затем он передает кортеж преобразованных значений в ваш обратный вызов.callback_args
кортеж дополнительных позиционных аргументов для передачи обратному вызову
callback_kwargs
словарь дополнительных аргументов ключевых слов для передачи обратному вызову
Как вызываются обратные вызовы¶
Все обратные вызовы вызываются следующим образом:
func(option, opt_str, value, parser, *args, **kwargs)
где
option
это экземпляр Option, который вызывает обратный вызов
opt_str
это строка опций в командной строке, которая вызывает обратный вызов. (Если использовалась сокращенная длинная опция,
opt_str
будет полной, канонической строкой опции - например, если пользователь ввел в командную строку--foo
как сокращение для--foobar
, тоopt_str
будет"--foobar"
).value
это аргумент данной опции, отображаемый в командной строке.
optparse
будет ожидать аргумента, только если установленtype
; типомvalue
будет тип, подразумеваемый типом опции. Еслиtype
для этой опции -None
(аргумент не ожидается), тоvalue
будетNone
. Еслиnargs
> 1, тоvalue
будет кортежем значений соответствующего типа.parser
это экземпляр OptionParser, управляющий всем этим процессом, в основном полезный тем, что через его атрибуты можно получить доступ к некоторым другим интересным данным:
parser.largs
текущий список оставшихся аргументов, то есть аргументов, которые были использованы, но не являются ни опциями, ни аргументами опций. Не стесняйтесь изменять
parser.largs
, например, добавляя в него дополнительные аргументы. (Этот список станетargs
, вторым возвращаемым значениемparse_args()
).parser.rargs
текущий список оставшихся аргументов, т.е. с удаленными
opt_str
иvalue
(если применимо), и только следующими за ними аргументами. Не стесняйтесь изменятьparser.rargs
, например, потребляя больше аргументов.parser.values
объект, в котором по умолчанию хранятся значения опций (экземпляр optparse.OptionValues). Это позволяет обратным вызовам использовать для хранения значений опций тот же механизм, что и в остальной части
optparse
; вам не нужно возиться с глобалами или закрытиями. Вы также можете получить доступ или изменить значение(я) любых опций, уже встречающихся в командной строке.
args
это кортеж произвольных позиционных аргументов, передаваемых через атрибут опции
callback_args
.kwargs
это словарь произвольных аргументов ключевых слов, передаваемых через
callback_kwargs
.
Возбуждение ошибок в обратном вызове¶
Функция обратного вызова должна поднять OptionValueError
, если возникли проблемы с опцией или ее аргументом(ами). optparse
перехватывает это и завершает работу программы, печатая в stderr сообщение об ошибке, которое вы предоставили. Ваше сообщение должно быть ясным, кратким, точным и содержать упоминание о неисправной опции. В противном случае пользователю будет трудно понять, что он сделал не так.
Пример обратного вызова 1: тривиальный обратный вызов¶
Вот пример опции обратного вызова, которая не принимает никаких аргументов и просто записывает, что опция была замечена:
def record_foo_seen(option, opt_str, value, parser):
parser.values.saw_foo = True
parser.add_option("--foo", action="callback", callback=record_foo_seen)
Конечно, это можно сделать с помощью действия "store_true"
.
Пример обратного вызова 2: проверка заказа опциона¶
Вот чуть более интересный пример: зафиксируйте факт появления -a
, но взорвитесь, если он появится после -b
в командной строке.
def check_order(option, opt_str, value, parser):
if parser.values.b:
raise OptionValueError("can't use -a after -b")
parser.values.a = 1
...
parser.add_option("-a", action="callback", callback=check_order)
parser.add_option("-b", action="store_true", dest="b")
Пример обратного вызова 3: проверка порядка опционов (обобщенный)¶
Если вы хотите использовать этот обратный вызов для нескольких похожих вариантов (установить флаг, но взорваться, если -b
уже был виден), его нужно немного доработать: сообщение об ошибке и флаг, который он устанавливает, должны быть обобщены.
def check_order(option, opt_str, value, parser):
if parser.values.b:
raise OptionValueError("can't use %s after -b" % opt_str)
setattr(parser.values, option.dest, 1)
...
parser.add_option("-a", action="callback", callback=check_order, dest='a')
parser.add_option("-b", action="store_true", dest="b")
parser.add_option("-c", action="callback", callback=check_order, dest='c')
Пример обратного вызова 4: проверка произвольного условия¶
Конечно, вы можете поместить туда любое условие - вы не ограничены проверкой значений уже определенных опций. Например, если у вас есть опции, которые не должны вызываться, когда луна полная, все, что вам нужно сделать, это:
def check_moon(option, opt_str, value, parser):
if is_moon_full():
raise OptionValueError("%s option invalid when moon is full"
% opt_str)
setattr(parser.values, option.dest, 1)
...
parser.add_option("--foo",
action="callback", callback=check_moon, dest="foo")
(Определение is_moon_full()
оставлено на усмотрение читателя).
Пример обратного вызова 5: фиксированные аргументы¶
Ситуация становится немного интереснее, когда вы определяете опции обратного вызова, которые принимают фиксированное количество аргументов. Указание того, что опция обратного вызова принимает аргументы, аналогично определению опции "store"
или "append"
: если вы определите type
, то опция принимает один аргумент, который должен быть преобразован к этому типу; если вы далее определите nargs
, то опция принимает nargs
аргументов.
Вот пример, который просто эмулирует стандартное действие "store"
:
def store_value(option, opt_str, value, parser):
setattr(parser.values, option.dest, value)
...
parser.add_option("--foo",
action="callback", callback=store_value,
type="int", nargs=3, dest="foo")
Обратите внимание, что optparse
берет на себя заботу о получении 3 аргументов и преобразовании их в целые числа; все, что вам нужно сделать, это сохранить их. (Или что-либо еще; очевидно, что для этого примера обратный вызов не нужен).
Пример обратного вызова 6: аргументы переменных¶
Ситуация осложняется, если вы хотите, чтобы опция принимала переменное количество аргументов. Для этого случая необходимо написать обратный вызов, поскольку optparse
не предоставляет для этого никаких встроенных возможностей. Кроме того, вам придется столкнуться с некоторыми тонкостями обычного разбора командной строки Unix, с которыми обычно справляется optparse
. В частности, обратные вызовы должны реализовывать обычные правила для голых --
и -
аргументов:
В качестве аргументов опции могут быть либо
--
, либо-
Голый
--
(если он не является аргументом какой-либо опции): прекратить обработку командной строки и отбросить--
.Голый
-
(если не является аргументом какой-либо опции): прекращает обработку командной строки, но сохраняет-
(добавляет его кparser.largs
)
Если вам нужна опция, принимающая переменное количество аргументов, то здесь есть несколько тонких и хитрых моментов. Точная реализация будет зависеть от того, на какие компромиссы вы готовы пойти в своем приложении (именно поэтому optparse
не поддерживает подобные вещи напрямую).
Тем не менее, вот попытка сделать обратный вызов для опции с переменными аргументами:
def vararg_callback(option, opt_str, value, parser):
assert value is None
value = []
def floatable(str):
try:
float(str)
return True
except ValueError:
return False
for arg in parser.rargs:
# stop on --foo like options
if arg[:2] == "--" and len(arg) > 2:
break
# stop on -a, but not on -3 or -3.0
if arg[:1] == "-" and len(arg) > 1 and not floatable(arg):
break
value.append(arg)
del parser.rargs[:len(value)]
setattr(parser.values, option.dest, value)
...
parser.add_option("-c", "--callback", dest="vararg_attr",
action="callback", callback=vararg_callback)
Расширение optparse
¶
Поскольку двумя основными факторами, определяющими, как optparse
интерпретирует параметры командной строки, являются действие и тип каждого параметра, наиболее вероятным направлением расширения является добавление новых действий и новых типов.
Добавление новых типов¶
Чтобы добавить новые типы, вам нужно определить собственный подкласс класса 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
принимает единственный строковый аргумент, который передается как есть в методOptionParser
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
класса 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
есть несколько классификаций действий:
- действия «магазин»
действия, в результате которых
optparse
сохраняет значение атрибута текущего экземпляра OptionValues; эти опции требуют, чтобы атрибутdest
был передан в конструктор Option.- «Набранные» действия
Действия, которые принимают значение из командной строки и ожидают, что оно будет определенного типа; точнее, строки, которая может быть преобразована к определенному типу. Эти опции требуют атрибута
type
в конструкторе Option.
Эти наборы пересекаются: некоторые «магазинные» действия по умолчанию - это "store"
, "store_const"
, "append"
и "count"
, а «печатные» действия по умолчанию - "store"
, "append"
и "callback"
.
Когда вы добавляете действие, вам нужно классифицировать его, включив хотя бы в один из следующих атрибутов класса Option (все они представляют собой списки строк):
- Option.ACTIONS¶
Все действия должны быть перечислены в разделе ACTIONS.
- Option.STORE_ACTIONS¶
Здесь также перечислены действия, связанные с «магазином».
- Option.TYPED_ACTIONS¶
«Набранные» действия дополнительно перечислены здесь.
- 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
присваивает действиям"extend"
тип по умолчанию"string"
, мы поместили действие"extend"
также вALWAYS_TYPED_ACTIONS
.MyOption.take_action()
реализует только это новое действие, а для стандартных действийoptparse
передает управление обратно вOption.take_action()
.values
- это экземпляр класса optparse_parser.Values, который предоставляет очень полезный методensure_value()
.ensure_value()
- это, по сути,getattr()
с предохранительным клапаном; он называется такvalues.ensure_value(attr, value)
Если атрибут
attr
вvalues
не существует или равенNone
, то ensure_value() сначала устанавливает его вvalue
, а затем возвращаетvalue
. Это очень удобно для таких действий, как"extend"
,"append"
и"count"
, все из которых накапливают данные в переменной и ожидают, что эта переменная будет определенного типа (список для первых двух, целое число для последнего). Использованиеensure_value()
означает, что скриптам, использующим ваше действие, не нужно беспокоиться о задании значения по умолчанию для рассматриваемых опций; они могут просто оставить значение по умолчаниюNone
, аensure_value()
позаботится о том, чтобы все было правильно, когда это потребуется.
Исключения¶
- exception optparse.OptionError¶
Возникает, если экземпляр
Option
создается с недопустимыми или противоречивыми аргументами.
- exception optparse.OptionConflictError¶
Возникает, если в
OptionParser
добавлены конфликтующие опции.
- exception optparse.OptionValueError¶
Возникает, если в командной строке встречается недопустимое значение опции.
- exception optparse.BadOptionError¶
Возникает, если в командной строке передана недопустимая опция.
- exception optparse.AmbiguousOptionError¶
Возникает, если в командной строке передана двусмысленная опция.