optparse
— Парсер для параметров командной строки
Не рекомендуется, начиная с версии 3.2: Модуль optparse
устарел и не будет разрабатываться в будущем;
разработка будет продолжена в модуле argparse
.
optparse
— более удобная, гибкая и мощная библиотека для парсинга
параметров командной строки, чем старый модуль getopt
. optparse
использует более декларативный стиль парсинга командной строки: вы создаёте
экземпляр OptionParser
, заполняете его параметрами и парсите
командную строку. optparse
позволяет пользователям указывать параметры в
обычном синтаксисе GNU/POSIX, а также генерирует для вас сообщения об
использовании и помощь.
Вот пример использования optparse
в простом скрипте:
from optparse import OptionParser
...
parser = OptionParser()
parser.add_option("-f", "--file", dest="filename",
help="write report to FILE", metavar="FILE")
parser.add_option("-q", "--quiet",
action="store_false", dest="verbose", default=True,
help="don't print status messages to stdout")
(options, args) = parser.parse_args()
С помощью данных нескольких строк кода пользователи вашего скрипта теперь могут, выполнять «обычные действия» в командной строке:
<yourscript> --file=outfile -q
При парсинге командной строки optparse
устанавливает атрибуты объекта
options
, возвращаемого parse_args()
, на основе введенных
пользователем в командной строке значений. Когда parse_args()
вернется из парсинга
этой командной строки, options.filename
будет "outfile"
, а
options.verbose
будет False
. optparse
поддерживает как длинные,
так и короткие параметры, позволяя объединять короткие параметры, а также
связывая параметры с их аргументами различными способами. Таким образом, все
следующие командные строки эквивалентны приведенному выше примеру:
<yourscript> -f outfile --quiet
<yourscript> --quiet --file outfile
<yourscript> -q -foutfile
<yourscript> -qfoutfile
Кроме того, пользователи могут выполнить следующее
<yourscript> -h
<yourscript> --help
и optparse
распечатает краткое пояснение параметров для скрипта:
Usage: <yourscript> [options]
Options:
-h, --help show this help message and exit
-f FILE, --file=FILE write report to FILE
-q, --quiet don't print status messages to stdout
где значение yourscript определяется во время выполнения (обычно из
sys.argv[0]
).
Фон
optparse
был специально разработан для поощрения создания программ с
простыми, традиционными интерфейсами командной строки. С этой целью он
поддерживает только наиболее распространенный синтаксис командной строки и
семантику, обычно используемые в Unix. Если вы не знакомы с этими соглашениями,
прочитайте данный раздел, чтобы ознакомиться с ними.
Терминология
- аргумент
строка, введенная в командной строке и переданная оболочкой в
execl()
илиexecv()
. В Python аргументы — это элементыsys.argv[1:]
(sys.argv[0]
— имя выполняемой программы). Unix-оболочки также используют термин «слово».Иногда желательно заменить список аргументов, отличный от
sys.argv[1:]
, поэтому вы должны читать «аргумент» как «элементsys.argv[1:]
или какого-либо другого списка, предоставленного вместоsys.argv[1:]
».- опция
используемый аргумент для предоставления дополнительной информации для управления или настройки выполнение программы. Есть много разных синтаксисов для опций; в традиционном синтаксисе Unix представляет собой дефис («-»), за которым следует одна буква например
-x
или-F
. Кроме того, традиционный синтаксис Unix допускает множественные параметры должны быть объединены в один аргумент, например-x -F
эквивалентен-xF
. Проект GNU представил--
, за которым последовала серия разделенных дефисом слов, например--file
или--dry-run
.optparse
реализует только два варианта синтаксиса.Некоторые другие синтаксисы опций:
- дефис, за которым следуют несколько букв, например,
-pf
(это не, то же самое, что несколько параметров, объединенных в один аргумент) - дефис, за которым следует целое слово, например
-file
(технически это эквивалентно предыдущему синтаксису, но обычно они не встречаются в одной и той же программе) - знак плюс, за которым следует одна буква, несколько букв или слово,
например
+f
,+rgb
- косая черта, за которой следует буква, или несколько букв, или слово,
например
/f
,/file
Данный синтаксис параметров не поддерживается
optparse
и никогда не будет. Это сделано намеренно: первые три являются нестандартными для любой среды, а последний имеет смысл только в том случае, если вы ориентируетесь исключительно на VMS, MS-DOS и/или Windows.- дефис, за которым следуют несколько букв, например,
- необязательный аргумент
следующий за опцией аргумент, тесно связанный с этой опцией и потребляется из списка аргументов, когда указана эта опция. С
optparse
, аргументы опции могут быть либо в отдельном аргументе опции:-f foo --file foo
или включены в тот же аргумент:
-ffoo --file=foo
Как правило, данная опция либо принимает аргумент, либо нет. Многим людям нужна функция «дополнительных аргументов опций», означающая, что некоторые опции будут принимать аргумент, если они его увидят, и не будут, если опции его не увидят. Это несколько спорно, потому что делает парсинг неоднозначным: если
-a
принимает необязательный аргумент, а-b
— совершенно другая опция, как мы интерпретируем-ab
? Из-за этой неоднозначностиoptparse
не поддерживает эту функцию.- позиционный аргумент
- что-то, что осталось в списке аргументов после парсинга опций, т.е. после того, как параметры и их аргументы были распарсены и удалены из файла списка аргументов.
- обязательная опция
- обязательно указываемый в командной строке параметр; обратите внимание на фразу
«Обязательная опция» в английском языке противоречит самому себе.
optparse
нет мешает вам реализовать необходимые параметры, но и не даёт вам большой помощи в этом.
Например, рассмотрим эту гипотетическую командную строку:
prog -v --report report.txt foo bar
-v
и --report
— две опции. Предполагая, что --report
принимает
один аргумент, report.txt
является аргументом опции. foo
и bar
являются позиционными аргументами.
Для чего нужны опции?
Опции используются для предоставления дополнительной информации для
тюнинга или настройки выполнения программы. Если неясно, опции обычно
необязательны. Программа должна нормально работать без каких-либо опций. (Проверьте
случайную программу из множеств инструментов Unix или GNU. Может ли она
работать без каких-либо опций и при этом иметь смысл? Основными
исключениями являются find
, tar
и dd
, — все из которых
являются чудаками-мутантами, справедливо критикуемые за нестандартный
синтаксис и запутанный интерфейс.)
Многие люди хотят, чтобы в их программах были «обязательные опции». Подумай об этом. Если это необходимо, то это не опции! Если есть какая-то абсолютно необходимая вашей программе для успешной работы информация, необходимы позиционные аргументы.
В качестве примера хорошего дизайна интерфейса командной строки рассмотрим
скромную утилиту cp
для копирования файлов. Не имеет особого смысла
пытаться копировать файлы, не указывая место назначения и хотя бы один
источник. Следовательно, cp
завершится ошибкой, если вы запускает ее без
аргументов. Однако у ее гибкий и полезный синтаксис, не
требующий никаких опций:
cp SOURCE DEST
cp SOURCE ... DEST-DIR
Только на этом можно далеко зайти. Большинство реализаций cp
предоставляют
множество опций для точного определения копирования файлов: вы можете
сохранить режим и время модификации, избежать перехода по символическим
ссылкам, задать вопрос перед удалением существующих файлов и т. д. Но ничто из
этого не отвлекает от основной миссии cp
, которая заключается в копировании
либо одного файла в другой, либо нескольких файлов в другой каталог.
Для чего нужны позиционные аргументы?
Позиционные аргументы предназначены для тех фрагментов информации, являющиеся абсолютно необходимы для запуска вашей программе.
Хороший пользовательский интерфейс должен иметь как можно меньше абсолютных требований. Если вашей программе требуется 17 различных фрагментов информации для успешного выполнения, не имеет большого значения как вы получите информацию от пользователя — большинство людей сдадутся и уйдут, прежде чем успешно запустят программу. Это применимо независимо от того, является ли пользовательский интерфейс командной строкой, файлом конфигурации или графическим интерфейсом: если вы предъявляете к своим пользователям много требований, большинство из них просто сдадутся.
Короче говоря, постарайтесь свести к минимуму объём обязательно предоставляемой информации пользователем. Используйте разумные значения по умолчанию, когда это возможно. Конечно, вы также хотите сделать свои программы достаточно гибкими. Вот для чего нужны опции. Опять же, не имеет значения, являются ли они записями в файле конфигурации, виджетами в диалоговом окне «Настройки» графического интерфейса или параметрами командной строки; чем больше опций вы реализуете, тем более гибкой становится ваша программа и тем сложнее становится её реализация. Излишняя гибкость, конечно, имеет и недостатки; слишком много опций может ошеломить пользователей и затруднить поддержку вашего кода.
Учебник по optparse
Хотя optparse
достаточно гибкий и мощный, в большинстве случаев его
просто использовать. В этом разделе рассматриваются шаблоны кода,
являющиеся общими для любой программы на базе optparse
.
Во-первых, вам нужно импортировать класс OptionParser; затем в начале основной программы создать экземпляр OptionParser:
from optparse import OptionParser
...
parser = OptionParser()
Затем вы можете приступить к определению опций. Основной синтаксис такой:
parser.add_option(opt_str, ...,
attr=value, ...)
Каждый опция имеет одну или несколько строк параметров, таких как -f
или
--file
, и несколько атрибутов параметров, сообщающих optparse
,
чего ожидать и что делать, когда он встречает данный параметр в командной
строке.
Как правило, каждая опция будет иметь, например, одну короткую строку опции и одну длинную строку опции:
parser.add_option("-f", "--file", ...)
Вы можете определить столько коротких и длинных строк параметров, сколько захотите (включая ноль), при условии, что в целом имеется хотя бы одна строка параметров.
Переданные в OptionParser.add_option()
строки параметров, фактически
являются метками для параметра, определённого этим вызовом. Для краткости мы
часто будем ссылаться на столкнуться с опцией в командной строке; на самом
деле optparse
встречает строки опций и ищет в них опции.
После того как все параметры определены, поручите optparse
распарсить командную строку вашей программы:
(options, args) = parser.parse_args()
(Если хотите, вы можете передать пользовательский список аргументов в
parse_args()
, но это редко бывает необходимо: по умолчанию используется
sys.argv[1:]
.)
parse_args()
возвращает два значения:
options
, объект, содержащий значения для всех ваших параметров. Например, если--file
принимает один строковый аргумент, тоoptions.file
будет именем файла, предоставленным пользователем, илиNone
, если пользователь не указал данный параметр.args
, список позиционных аргументов, оставшихся после парсинга опций.
В этом учебном разделе рассматриваются только четыре наиболее важных атрибута
параметров: action
, type
, dest
(назначение) и help
. Из них action
является
наиболее фундаментальным.
Понимание действий опций
Действия говорят optparse
, что делать, когда он встречает опцию в
командной строке. В optparse
жестко закодирован фиксированное множество
действий; добавление новых действий — это дополнительная тема, рассмотренная в
разделе Расширение optparse. Большинство действий говорят
optparse
сохранить значение в некоторой переменной, например, взять
строку из командной строки и сохранить её в атрибуте options
.
Если вы не укажете действие параметра, optparse
по умолчанию будет
store
.
Действие store
Наиболее распространенное действие параметра — store
, указывающее
optparse
где взять следующий аргумент (или оставшуюся часть текущего
аргумента), убедиться, что у него правильный тип, и сохраняет его в выбранном
месте назначения.
Например:
parser.add_option("-f", "--file",
action="store", type="string", dest="filename")
Теперь создадим фальшивую командную строку и попросим optparse
распарсить
её:
args = ["-f", "foo.txt"]
(options, args) = parser.parse_args(args)
Когда optparse
видит строку параметра -f
, он использует
аргумент foo.txt
, и сохраняет его в options.filename
. Итак, после
вызова parse_args()
options.filename
будет "foo.txt"
.
Другие типы опций, поддерживаемые optparse
— это int
и float
. Вот опция, ожидающая целочисленный аргумент:
parser.add_option("-n", type="int", dest="num")
Обратите внимание, что у этой опции нет длинной строки опций, что вполне
приемлемо. Кроме того, здесь нет явного действия, т. к. по умолчанию
используется store
.
Давайте разберем ещё одну фальшивую командную строку. На данный раз мы
поместим аргумент опции прямо напротив опции: поскольку -n42
(один
аргумент) эквивалентен -n 42
(два аргумента), код
(options, args) = parser.parse_args(["-n42"])
print(options.num)
напечатает 42
.
Если вы не укажете тип, optparse
предполагает string
. В сочетании с
тем фактом, что действие по умолчанию — store
, это означает, что наш первый
пример может быть намного короче:
parser.add_option("-f", "--file", dest="filename")
Если вы не укажете место назначения, optparse
вычислит разумное значение
по умолчанию из строк параметров: если первая длинная строка параметров —
--foo-bar
, то место назначения по умолчанию — foo_bar
. Если длинных
строк параметров нет, optparse
просматривает первую короткую строку
параметров: назначением по умолчанию для -f
является f
.
optparse
также включает встроенный тип complex
. Добавление типов
приведено в разделе Расширение optparse.
Обработка логических (флаговых) опций
Опциональные флаги устанавливают переменную в значение истина или ложь, когда
видна определенная опция. Они довольно распространены. optparse
поддерживает их двумя отдельными действиями: store_true
и store_false
.
Например, у вас есть флаг verbose
, включаемый с помощью
-v
и отключаемый с помощью -q
:
parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose")
Здесь у нас есть две разных опции с одним и тем же пунктом назначения, что совершенно нормально. (Это просто означает, что вы должны быть немного осторожны при установке значений по умолчанию, — см. ниже.)
Когда optparse
встречает -v
в командной строке, он устанавливает
options.verbose
в True
; когда он встречает -q
, options.verbose
устанавливается на False
.
Другие действия
Другие действия, поддерживаемые optparse
:
"store_const"
- сохраняет постоянное значение
"append"
- добавляет аргумент опции в список
"count"
- увеличивает счётчик на единицу
"callback"
- вызывает указанную функцию
Они рассмотрены в разделах Справочное руководство и Опции обратных вызовов.
Значения по умолчанию
Все приведенные выше примеры включают установку некоторой переменной
(«назначение»), когда видны определённые параметры командной строки. Что
произойдет, если данные опции никогда не будут видны? Поскольку мы не
предоставили никаких значений по умолчанию, все они установлены на None
.
Обычно это нормально, но иногда вам нужно больше контроля. optparse
позволяет указать значение по умолчанию для каждого пункта назначения,
назначаемые перед парсингом командной строки.
Сначала рассмотрим подробный/тихий пример. Если мы хотим, чтобы optparse
установил verbose
в True
, если -q
не виден, мы можем сделать следующее:
parser.add_option("-v", action="store_true", dest="verbose", default=True)
parser.add_option("-q", action="store_false", dest="verbose")
Поскольку значения по умолчанию применяются к назначению, а не к какой-либо конкретной опции, и данные две опции имеют одно и то же место назначения, это в точности эквивалентно:
parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose", default=True)
Учти это:
parser.add_option("-v", action="store_true", dest="verbose", default=False)
parser.add_option("-q", action="store_false", dest="verbose", default=True)
Опять же, значением по умолчанию для verbose
будет True
: учитывается
последнее значение по умолчанию, указанное для любого конкретного места
назначения.
Более понятным способом указать значения по умолчанию является метод
set_defaults()
класса OptionParser, вызываемый в любое время
перед вызовом parse_args()
:
parser.set_defaults(verbose=True)
parser.add_option(...)
(options, args) = parser.parse_args()
Как и прежде, учитывается последнее значение, указанное для данной опции назначения. Для ясности попробовать использовать тот или иной метод установки значений по умолчанию, а не оба.
Генерация справки
Способность optparse
автоматически генерировать справку и текст
использования полезна для создания удобных интерфейсов командной строки. Все,
что вам нужно сделать, это указать значение help
для каждой
опции и, возможно, короткое сообщение об использовании для всей вашей
программы. Вот OptionParser, заполненный удобными (задокументированными)
опциями:
usage = "usage: %prog [options] arg1 arg2"
parser = OptionParser(usage=usage)
parser.add_option("-v", "--verbose",
action="store_true", dest="verbose", default=True,
help="make lots of noise [default]")
parser.add_option("-q", "--quiet",
action="store_false", dest="verbose",
help="be vewwy quiet (I'm hunting wabbits)")
parser.add_option("-f", "--filename",
metavar="FILE", help="write output to FILE")
parser.add_option("-m", "--mode",
default="intermediate",
help="interaction mode: novice, intermediate, "
"or expert [default: %default]")
Если optparse
встречает -h
или --help
в командной строке, или
если вы просто вызываете parser.print_help()
, он выводит на стандартный
вывод следующее:
Usage: <yourscript> [options] arg1 arg2
Options:
-h, --help show this help message and exit
-v, --verbose make lots of noise [default]
-q, --quiet be vewwy quiet (I'm hunting wabbits)
-f FILE, --filename=FILE
write output to FILE
-m MODE, --mode=MODE interaction mode: novice, intermediate, or
expert [default: intermediate]
(Если вывод справки запускается параметром справки, optparse
завершает
работу после печати текста справки.)
Здесь многое делается для того, чтобы помочь optparse
сгенерировать
наилучшее справочное сообщение:
сценарий определяет свое собственное сообщение об использовании:
usage = "usage: %prog [options] arg1 arg2"
optparse
расширяет%prog
в строке использования до имени текущей программы, т. е.os.path.basename(sys.argv[0])
. Затем расширенная строка печатается перед подробной справкой по параметрам.Если вы не укажете строку использования,
optparse
использует мягкое, но разумное значение по умолчанию:"Usage: %prog [options]"
, что нормально, если ваш сценарий не принимает никаких позиционных аргументов.каждая опция определяет строку справки и не беспокоится о переносе строк —
optparse
заботится о переносе строк и о том, чтобы вывод справки выглядел хорошо.принимающие значение опции, указывают на данный факт в своём автоматически сгенерированном справочном сообщении, например, для опции «mode»:
-m MODE, --mode=MODE
Здесь «MODE» называется метапеременной: она обозначает аргумент, который пользователь должен передать в
-m
/--mode
. По умолчаниюoptparse
преобразует имя переменной назначения в верхний регистр и использует его для метапеременной. Иногда это не то, что вам нужно, например, параметр--filename
явно задаётmetavar="FILE"
, что приводит к этому автоматически сгенерированному пояснению параметра:-f FILE, --filename=FILE
Это важно не только для экономии места: написанный вручную текст справки использует метапеременную
FILE
, чтобы указать пользователю, что существует связь между полуформальным синтаксисом-f FILE
и неформальным семантическим описанием «записывает вывод в ФАЙЛ». . Это простой, но эффективный способ сделать текст справки более понятным и полезным для конечных пользователей.параметры, имеющие значение по умолчанию, могут включать
%default
в строке справки, аoptparse
заменит его наstr()
значения параметра по умолчанию. Если параметр не имеет значения по умолчанию (или значение по умолчанию —None
),%default
расширяется доnone
.
Параметры группировки
При работе со многими параметрами удобно сгруппировать данные параметры для
лучшего вывода справки. OptionParser
может содержать несколько групп
опций, каждая из которых может содержать несколько опций.
Группа параметров получается с использованием класса OptionGroup
:
-
class
optparse.
OptionGroup
(parser, title, description=None) где
- parser — это экземпляр
OptionParser
, в который будет вставлена группа - title — название группы
- description, необязательный, представляет собой длинное описание группы
- parser — это экземпляр
OptionGroup
наследуется от OptionContainer
(например,
OptionParser
), поэтому для добавления параметра в группу можно
использовать метод add_option()
.
Как только все параметры объявлены, с помощью метода OptionParser
add_option_group()
группа добавляется к ранее определенному
парсеру.
Продолжая работу с парсером, определенным в предыдущем
разделе, добавить OptionGroup
к парсеру несложно:
group = OptionGroup(parser, "Dangerous Options",
"Caution: use these options at your own risk. "
"It is believed that some of them bite.")
group.add_option("-g", action="store_true", help="Group option.")
parser.add_option_group(group)
Это приведёт к следующему выводу справки:
Usage: <yourscript> [options] arg1 arg2
Options:
-h, --help show this help message and exit
-v, --verbose make lots of noise [default]
-q, --quiet be vewwy quiet (I'm hunting wabbits)
-f FILE, --filename=FILE
write output to FILE
-m MODE, --mode=MODE interaction mode: novice, intermediate, or
expert [default: intermediate]
Dangerous Options:
Caution: use these options at your own risk. It is believed that some
of them bite.
-g Group option.
Немного более полный пример может включать использование более одной группы: все ещё расширяя предыдущий пример:
group = OptionGroup(parser, "Dangerous Options",
"Caution: use these options at your own risk. "
"It is believed that some of them bite.")
group.add_option("-g", action="store_true", help="Group option.")
parser.add_option_group(group)
group = OptionGroup(parser, "Debug Options")
group.add_option("-d", "--debug", action="store_true",
help="Print debug information")
group.add_option("-s", "--sql", action="store_true",
help="Print all SQL statements executed")
group.add_option("-e", action="store_true", help="Print every action done")
parser.add_option_group(group)
это приводит к следующему результату:
Usage: <yourscript> [options] arg1 arg2
Options:
-h, --help show this help message and exit
-v, --verbose make lots of noise [default]
-q, --quiet be vewwy quiet (I'm hunting wabbits)
-f FILE, --filename=FILE
write output to FILE
-m MODE, --mode=MODE interaction mode: novice, intermediate, or expert
[default: intermediate]
Dangerous Options:
Caution: use these options at your own risk. It is believed that some
of them bite.
-g Group option.
Debug Options:
-d, --debug Print debug information
-s, --sql Print all SQL statements executed
-e Print every action done
Ещё один интересный метод, особенно при программной работе с группами опций:
-
OptionParser.
get_option_group
(opt_str) Возвращает
OptionGroup
, к которому принадлежит короткая или длинная строка опции opt_str (например,'-o'
или'--option'
). Если такогоOptionGroup
нет, возвращаетNone
.
Печать строки версии
Подобно краткой строке использования, optparse
также может печатать
строку версии для вашей программы. Вы должны предоставить строку в качестве
аргумента version
для OptionParser:
parser = OptionParser(usage="%prog [-f] [-q]", version="%prog 1.0")
%prog
расширяется так же, как и usage
. Кроме того, version
может
содержать что угодно. Когда вы его указываете, optparse
автоматически
добавляет в ваш парсер параметр --version
. Если он встречает эту опцию
в командной строке, он расширяет вашу строку version
(путём замены
%prog
), выводит её на стандартный вывод и завершает работу.
Например, если ваш скрипт называется /usr/bin/foo
:
$ /usr/bin/foo --version
foo 1.0
Следующие два метода можно использовать для печати и получения строки
version
:
-
OptionParser.
print_version
(file=None) Выводит сообщение о версии для текущей программы (
self.version
) в file (стандартный вывод по умолчанию). Как и в случае сprint_usage()
, любое вхождение%prog
вself.version
заменяется именем текущей программы. Ничего не делает, еслиself.version
пуст или не определён.
-
OptionParser.
get_version
() То же, что и
print_version()
, но возвращает строку версии вместо её вывода.
Как optparse
обрабатывает ошибки?
Существует два широких класса ошибок, о которых optparse
должен
беспокоиться: ошибки программиста и ошибки пользователя. Ошибки программиста
обычно представляют собой ошибочные вызовы OptionParser.add_option()
,
например, неверные строки опций, неизвестные атрибуты опций, отсутствующие
атрибуты опций и т. д. Они обрабатываются обычным способом: создает исключение
(либо optparse.OptionError
, либо TypeError
) и дать программе
обрушиться.
Обработка пользовательских ошибок гораздо важнее, поскольку они гарантированно
произойдут независимо от того, насколько стабилен ваш код. optparse
может автоматически обнаруживать некоторые пользовательские ошибки, такие как
неверные аргументы опции (передача -n 4x
, где -n
принимает
целочисленный аргумент), отсутствующие аргументы (-n
в конце командной
строки, где -n
принимает аргумент любого типа). Кроме того, вы можете
вызвать OptionParser.error()
, чтобы сообщить об ошибке, определяемой
приложением:
(options, args) = parser.parse_args()
...
if options.a and options.b:
parser.error("options -a and -b are mutually exclusive")
В любом случае optparse
обрабатывает ошибку одинаково: выводит сообщение
об использовании программы и сообщение об ошибке в стандартную ошибку и
завершает работу со статусом ошибки 2.
Рассмотрим первый пример выше, где пользователь передает 4x
опции,
принимающая целое число:
$ /usr/bin/foo -n 4x
Usage: foo [options]
foo: error: option -n: invalid integer value: '4x'
Или, когда пользователь вообще не может передать значение:
$ /usr/bin/foo -n
Usage: foo [options]
foo: error: -n option requires an argument
Сгенерированные сообщения об ошибках optparse
всегда должны упоминать
параметр, связанный с ошибкой; обязательно выполняет то же самое при вызове
OptionParser.error()
из кода вашего приложения.
Если поведение обработки ошибок по умолчанию optparse
не соответствует
вашим потребностям, вам потребуется создать подкласс OptionParser и
переопределить его методы exit()
и/или
error()
.
Собираем все вместе
Вот как обычно выглядят сценарии на основе optparse
from optparse import OptionParser
...
def main():
usage = "usage: %prog [options] arg"
parser = OptionParser(usage)
parser.add_option("-f", "--file", dest="filename",
help="read data from FILENAME")
parser.add_option("-v", "--verbose",
action="store_true", dest="verbose")
parser.add_option("-q", "--quiet",
action="store_false", dest="verbose")
...
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error("incorrect number of arguments")
if options.verbose:
print("reading %s..." % options.filename)
...
if __name__ == "__main__":
main()
Справочное руководство
Создание парсера
Первым шагом в использовании optparse
является создание экземпляра
OptionParser.
-
class
optparse.
OptionParser
(...) Конструктор OptionParser не имеет обязательных аргументов, но имеет ряд необязательных ключевых аргументов. Вы всегда должны передавать их как ключевые аргументы, т. е. не полагаться на порядок, в котором объявлены аргументы.
usage
(по умолчанию:"%prog [options]"
)- Сводка использования для печати, когда ваша программа запускается
неправильно или с опцией
помощи. Когда
optparse
печатает строку использования, она расширяется%prog
доos.path.basename(sys.argv[0])
(или доprog
, если вы передали данный ключевой аргумент). Чтобы подавить сообщение об использовании, передайте методу специальное значениеoptparse.SUPPRESS_USAGE
. option_list
(по умолчанию:[]
)- Список объектов Option для заполнения парсера. Опции в
option_list
добавляются после любых опций вstandard_option_list
(a атрибут класса, который может быть установлен подклассами OptionParser), но раньше любая версия или опции справки. Устарело; используйтеadd_option()
после вместо этого создаёт парсер. option_class
(по умолчанию: optparse.Option)- Класс для использования при добавлении параметров в парсер
add_option()
. version
(по умолчанию:None
)- Строка версии для печати, когда пользователь предоставляет параметр версии.
Если указано истинное значение для
version
,optparse
автоматически добавит опцию версии с единственной строкой параметра--version
. Подстрока%prog
расширяется так же, как и дляusage
. conflict_handler
(по умолчанию:"error"
)- Указывает, что делать, если параметры с конфликтующими строками параметров добавлены в парсер; см. раздел Конфликты между опциями.
description
(по умолчанию:None
)- Абзац текста, дающий краткий обзор вашей программы.
optparse
переформатирует данный абзац, чтобы он соответствовал текущей ширине терминала и печатает его, когда пользователь запрашивает помощь (послеusage
, но до списка опций). formatter
(по умолчанию: новыйIndentedHelpFormatter
)- Экземпляр optparse.HelpFormatter, используемый для печати текста
справки.
optparse
предоставляет для этой цели два конкретных класса: IndentedHelpFormatter и TitledHelpFormatter. add_help_option
(по умолчанию:True
)- Если истина,
optparse
добавит параметр справки (со строками параметров-h
и--help
) парсеру. prog
- Строка, используемая при расширении
%prog
вusage
иversion
вместоos.path.basename(sys.argv[0])
. epilog
(по умолчанию:None
)- Абзац текста справки для печати после опции help.
Заполнение парсера
Есть несколько способов заполнить парсер параметрами. Предпочтительным способом
является использование OptionParser.add_option()
, как показано в разделе
Учебник по optparse. add_option()
можно вызвать одним из двух
способов:
- передать ему экземпляр Option (как возвращено
make_option()
) - передать ему любую комбинацию позиционных и ключевых аргументов,
являющиеся приемлемыми для
make_option()
(т. е. конструктору Option), и он создаст для вас экземпляр Option
Другой альтернативой является передача списка предварительно сконструированных экземпляров Option в конструктор OptionParser, как показано ниже:
option_list = [
make_option("-f", "--filename",
action="store", type="string", dest="filename"),
make_option("-q", "--quiet",
action="store_false", dest="verbose"),
]
parser = OptionParser(option_list=option_list)
(make_option()
— это функция фабрика для создания экземпляров Option; в
настоящее время это псевдоним конструктора Option. В будущей версии
optparse
Option может быть разделен на несколько классов, и
make_option()
выберет правильный класс для создания экземпляра. Не
создавайте экземпляр Option напрямую.)
Определение опций
Каждый экземпляр Option представляет множество синонимичных строк параметров
командной строки, например -f
и --file
. Вы можете указать любое
количество коротких или длинных строк параметров, но вы должны указать хотя бы
одну общую строку параметров.
Канонический способ создания экземпляра Option
— метод
add_option()
OptionParser
.
-
OptionParser.
add_option
(option) -
OptionParser.
add_option
(*opt_str, attr=value, ...) Чтобы определить параметр только с короткой строкой параметра:
parser.add_option("-f", attr=value, ...)
И определить параметр только с длинной строкой параметра:
parser.add_option("--foo", attr=value, ...)
Ключевые аргументы определяют атрибуты нового объекта Option. Наиболее важным атрибутом параметра является
action
, и он во многом определяет, какие другие атрибуты являются релевантными или обязательными. Если вы передаете нерелевантные атрибуты параметров или не передаете обязательные,optparse
вызывает исключениеOptionError
, объясняющее вашу ошибку.Параметр action определяет, что делает
optparse
, когда встречает данный параметр в командной строке. Стандартные действия опций жестко запрограммированы вoptparse
:"store"
- сохраняет аргумент этой опции (по умолчанию)
"store_const"
- сохраняет постоянное значение
"store_true"
- сохраняет
True
"store_false"
- сохраняет
False
"append"
- добавляет аргумент этой опции в список
"append_const"
- добавляет постоянное значение в список
"count"
- увеличивает счётчик на единицу
"callback"
- вызывает указанную функцию
"help"
- распечатывает сообщение об использовании, включая все параметры и документацию для них
(Если вы не укажете действие, по умолчанию используется
"store"
. Для этого действия вы также можете указать атрибуты опцииtype
иdest
; см. Стандартные действия опций.)
Как видите, большинство действий связаны с сохранением или обновлением значения
где-либо. optparse
всегда создаёт для этого специальный объект, условно
называемый options
(это экземпляр optparse.Values
). Аргументы
опции (и различные другие значения) хранятся как атрибуты этого объекта в
соответствии с атрибутом опции dest
(назначение).
Например, когда вы вызываете:
parser.parse_args()
Одно из первых действий optparse
— создание объекта options
:
options = Values()
Если одна из опций в этом парсере определена с помощью
parser.add_option("-f", "--file", action="store", type="string", dest="filename")
и анализируемая командная строка включает любое из следующего:
-ffoo
-f foo
--file=foo
--file foo
то optparse
, увидев эту опцию, сделает эквивалент
options.filename = "foo"
Атрибуты опций type
и dest
почти так же важны,
как action
, но action
— единственный,
имеющий смысл для всех опций.
Атрибуты опции
Следующие атрибуты параметров могут быть переданы в качестве ключевых
аргументов в OptionParser.add_option()
. Если вы передаете атрибут
параметра, не относящийся к конкретному параметру, или не передаете
обязательный атрибут параметра, optparse
вызывает OptionError
.
-
Option.
action
(по умолчанию:
"store"
)Определяет поведение
optparse
, когда данный параметр отображается в командной строке; доступные опции задокументированы здесь.
-
Option.
type
(по умолчанию:
"string"
)Тип аргумента, ожидаемый этой опцией (например,
"string"
или"int"
); доступные типы опций задокументированы здесь.
-
Option.
dest
(по умолчанию: получено из строк опций)
Если действие параметра подразумевает запись или изменение значения где-либо, это сообщает
optparse
, куда его записывает:dest
называет атрибут объектаoptions
, которыйoptparse
создаёт при парсинге командной строки.
-
Option.
default
Значение, используемое для назначения этого параметра, если данный параметр не отображается в командной строке. См. также
OptionParser.set_defaults()
.
-
Option.
nargs
(по умолчанию: 1)
Сколько аргументов типа
type
должно использоваться, когда отображается данный параметр. Если > 1,optparse
сохранит кортеж значений доdest
.
-
Option.
const
Для действий, сохраняющих постоянное значение, постоянное значение для сохранения.
-
Option.
choices
Для опций типа
"choice"
— список выбираемых пользователем строк.
-
Option.
callback
Для опций с действием
"callback"
, вызываемый для вызова, когда эта опция видна. См. раздел Опции обратных вызовов для получения подробной информации об аргументах, передаваемых вызываемому объекту.
-
Option.
callback_args
-
Опция.
callback_kwargs
Дополнительные позиционные и ключевые аргументы для передачи в
callback
после четырех стандартных аргументов обратного вызова.
-
Option.
help
Текст справки для печати для этого параметра при перечислении всех доступных параметров после того, как пользователь введет параметр
help
(например,--help
). Если справочный текст не указан, опция будет указана без справочного текста. Чтобы скрыть эту опцию, используйте специальное значениеoptparse.SUPPRESS_HELP
.
-
Option.
metavar
(по умолчанию: получено из строк опций)
Заменяет аргумент(ы) опции для использования при печати текста справки. Пример см. в разделе Учебник по optparse.
Стандартные действия опций
Различные действия опций имеют немного разные требования и эффекты. Большинство
действий имеют несколько соответствующих атрибутов параметров,
для управления поведением optparse
; у некоторых есть
обязательные атрибуты, указывающие для любой использующей это действие опции.
"store"
[актуально:type
,dest
,nargs
,choices
]За опцией должен следовать аргумент, преобразуемый в значение в соответствии с
type
и сохраняется вdest
. Еслиnargs
> 1, из командной строки будут использоваться несколько аргументов; все они будут преобразованы в соответствии сtype
и сохранены вdest
в виде кортежа. См. раздел Стандартные типы опций.Если указан
choices
(список или кортеж строк), по умолчанию используется тип"choice"
.Если
type
не указан, по умолчанию используется"string"
.Если
dest
не указан,optparse
получает пункт назначения из первой длинной строки параметров (например,--foo-bar
подразумеваетfoo_bar
). Если длинных строк параметров нет,optparse
получает место назначения из первой короткой строки параметров (например,-f
подразумеваетf
).Пример:
parser.add_option("-f") parser.add_option("-p", type="float", nargs=3, dest="point")
Как он парсит командную строку:
-f foo.txt -p 1 -3.5 4 -fbar.txt
optparse
установитoptions.f = "foo.txt" options.point = (1.0, -3.5, 4.0) options.f = "bar.txt"
"store_const"
[требуется:const
; актуально:dest
]Значение
const
хранится вdest
.Пример:
parser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbose") parser.add_option("-v", "--verbose", action="store_const", const=1, dest="verbose") parser.add_option("--noisy", action="store_const", const=2, dest="verbose")
Если
--noisy
виден,optparse
установитoptions.verbose = 2
"store_true"
[актуально:dest
]Особый случай
"store_const"
, в котором хранятся значения отTrue
доdest
."store_false"
[актуально:dest
]Как
"store_true"
, но хранитFalse
.Пример:
parser.add_option("--clobber", action="store_true", dest="clobber") parser.add_option("--no-clobber", action="store_false", dest="clobber")
"append"
[актуально:type
,dest
,nargs
,choices
]За опцией должен следовать аргумент, который добавляется к списку в
dest
. Если значение по умолчанию дляdest
не указано, автоматически создаётся пустой список, когдаoptparse
впервые встречает данный параметр в командной строке. Еслиnargs
> 1, используется несколько аргументов, и кdest
добавляется кортеж длинойnargs
.Значения по умолчанию для
type
иdest
такие же, как и для действия"store"
.Пример:
parser.add_option("-t", "--tracks", action="append", type="int")
Если в командной строке отображается
-t3
, тоoptparse
делает то же самое:options.tracks = [] options.tracks.append(int("3"))
Если чуть позже будет виден
--tracks=4
, значит, так оно и есть:options.tracks.append(int("4"))
Действие
append
вызывает методappend
для текущего значения параметра. Это означает, что любое указанное значение по умолчанию должно иметь методappend
. Это также означает, что если значение по умолчанию не пусто, элементы по умолчанию будут присутствовать в проанализированном значении для параметра, а любые значения из командной строки будут добавлены после данных значений по умолчанию:>>> parser.add_option("--files", action="append", default=['~/.mypkg/defaults']) >>> opts, args = parser.parse_args(['--files', 'overrides.mypkg']) >>> opts.files ['~/.mypkg/defaults', 'overrides.mypkg']
"append_const"
[требуется:const
; актуально:dest
]Аналогично
"store_const"
, но кdest
добавляется значениеconst
; как и в случае с"append"
,dest
по умолчанию имеет значениеNone
, и пустой список автоматически создаётся при первом появлении этого параметра."count"
[актуально:dest
]Увеличивает целое число, хранящееся в
dest
. Если значение по умолчанию не указано,dest
устанавливается равным нулю перед первым увеличением.Пример:
parser.add_option("-v", action="count", dest="verbosity")
В первый раз, когда
-v
появляется в командной строке,optparse
делает то же самое:options.verbosity = 0 options.verbosity += 1
Каждое последующее вхождение
-v
приводит кoptions.verbosity += 1
"callback"
[требуется:callback
; соответствующие:type
,nargs
,callback_args
,callback_kwargs
]Вызвать функцию, указанную в
callback
, вызываемая какfunc(option, opt_str, value, parser, *args, **kwargs)
Подробнее см. в разделе Опции обратных вызовов.
"help"
Выводит полное справочное сообщение для всех опций в текущем парсере опций. Справочное сообщение создаётся из строки
usage
, передаваемой конструктору OptionParser, и строкиhelp
, передаваемой каждому параметру.Если для опции не указана строка
help
, она все равно будет указана в справочном сообщении. Чтобы полностью исключить параметр, используйте специальное значениеoptparse.SUPPRESS_HELP
.optparse
автоматически добавляет параметрhelp
ко всем OptionParsers, поэтому обычно вам не нужно его создавать.Пример:
from optparse import OptionParser, SUPPRESS_HELP # обычно опция справки добавляется автоматически, но это может # быть переопределно с помощью аргумента add_help_option parser = OptionParser(add_help_option=False) parser.add_option("-h", "--help", action="help") parser.add_option("-v", action="store_true", dest="verbose", help="Be moderately verbose") parser.add_option("--file", dest="filename", help="Input file to read data from") parser.add_option("--secret", help=SUPPRESS_HELP)
Если
optparse
увидит-h
или--help
в командной строке, он выведет что-то вроде следующего справочного сообщения на стандартный вывод (при условии, чтоsys.argv[0]
— это"foo.py"
):Usage: foo.py [options] Options: -h, --help Show this help message and exit -v Be moderately verbose --file=FILENAME Input file to read data from
После печати справочного сообщения
optparse
завершает ваш процесс сsys.exit(0)
."version"
Выводит номер версии, предоставленный OptionParser, на стандартный вывод и завершает работу. Номер версии фактически форматируется и печатается методом
print_version()
OptionParser. Как правило, имеет значение только в том случае, если аргументversion
передаётся конструктору OptionParser. Как и в случае с параметрамиhelp
, вы редко будете создавать параметрыversion
, посколькуoptparse
автоматически добавляет их при необходимости.
Стандартные типы опций
optparse
имеет пять встроенных типов опций: "string"
, "int"
,
"choice"
, "float"
и "complex"
. Если вам нужно добавить новые типы
опций, см. раздел Расширение optparse.
Аргументы строковых опций никак не проверяются и не преобразуются: текст в командной строке сохраняется в месте назначения (или передаётся обратному вызову) как есть.
Целочисленные аргументы (тип "int"
) парсится следующим образом:
- если число начинается с
0x
, оно парсится как шестнадцатеричное число. - если номер начинается с
0
, он парсится как восьмеричное число. - если номер начинается с
0b
, он парсится как двоичное число. - в противном случае число парсится как десятичное число.
Преобразование выполняется путём вызова int()
с соответствующим
основанием (2, 8, 10 или 16). Если это не удастся, то же самое произойдет с
optparse
, хотя и с более полезным сообщением об ошибке.
Аргументы параметров "float"
и "complex"
преобразуются напрямую с
помощью float()
и complex()
с аналогичной обработкой ошибок.
Параметры "choice"
являются подтипом параметров "string"
. Атрибут опции
choices
(последовательность строк) определяет множество
допустимых аргументов опции. optparse.check_choice()
сравнивает
предоставленные пользователем аргументы параметров с этим основным списком и
вызывает OptionValueError
, если задана недопустимая строка.
Парсинг аргументов
Весь смысл создания и заполнения OptionParser заключается в вызове его метода
parse_args()
:
(options, args) = parser.parse_args(args=None, values=None)
где находятся входные параметры:
args
- список аргументов для обработки (по умолчанию:
sys.argv[1:]
) values
- объект
optparse.Values
для хранения аргументов опций (по умолчанию: a новый экземплярValues
) – если вы указываете существующий объект, то значения по умолчанию для него не будут инициализированы
и возвращаемые значения:
options
- тот же объект, переданный как
values
, или созданныйoptparse
экземпляр optparse.Values. args
- оставшиеся позиционные аргументы после обработки всех опций
Наиболее распространенное использование — не указывать ключевой аргумент.
Если вы укажете values
, он будет изменён повторными вызовами
setattr()
(примерно по одному для каждого аргумента опции, хранящегося в
пункте назначения опции) и возвращён parse_args()
.
Если parse_args()
обнаруживает какие-либо ошибки в списке аргументов, он
вызывает метод error()
OptionParser с соответствующим сообщением об
ошибке конечного пользователя. Это в конечном итоге завершает ваш процесс со
статусом выхода 2 (традиционный статус выхода Unix для ошибок командной
строки).
Запрос и управление вашим парсером опций
Поведение парсера параметров по умолчанию можно немного настроить, и вы также можете покопаться в своём парсере параметров и посмотреть, что там. OptionParser предоставляет несколько помогающих методов:
-
OptionParser.
disable_interspersed_args
() Настраивает парсинг на остановку на первой не опции. Например, если
-a
и-b
являются простыми параметрами, не принимающими аргументов,optparse
обычно принимает данный синтаксис:prog -a arg1 -b arg2
и рассматривает его как эквивалент
prog -a -b arg1 arg2
Чтобы отключить эту функцию, вызовите по номеру
disable_interspersed_args()
. Это восстанавливает традиционный синтаксис Unix, где парсинг параметров останавливается с первым аргументом, не являющимся параметром.Используйте это, если у вас есть командный процессор, запускающий другую команду, имеющую собственные параметры, и вы хотите убедиться, что данные параметры не перепутаны. Например, у каждой команды может быть свое множество параметров.
-
OptionParser.
enable_interspersed_args
() Настраивает парсинг так, чтобы он не останавливался на первой не опции, что позволяет чередовать переключатели с аргументами команды. Это поведение по умолчанию.
-
OptionParser.
get_option
(opt_str) Возвращает экземпляр Option со строкой параметра opt_str или
None
, если ни один из параметров не имеет строки параметра.
-
OptionParser.
has_option
(opt_str) Возвращает
True
, если OptionParser имеет опцию со строкой опции opt_str (например,-q
или--verbose
).
-
OptionParser.
remove_option
(opt_str) Если
OptionParser
имеет параметр, соответствующий opt_str, данный параметр удаляется. Если данный параметр предоставляет какие-либо другие строки параметров, все данные строки параметров становятся недействительными. Если opt_str не встречается ни в одной опции, принадлежащей этомуOptionParser
, вызываетсяValueError
.
Конфликты между опциями
Если вы не будете осторожны, легко определить параметры с конфликтующими строками параметров:
parser.add_option("-n", "--dry-run", ...)
...
parser.add_option("-n", "--noisy", ...)
(Это особенно верно, если вы определили свой собственный подкласс OptionParser с некоторыми стандартными параметрами.)
Каждый раз, когда вы добавляете параметр, optparse
проверяет наличие
конфликтов с существующими параметрами. Если он их находит, он вызывает текущий
механизм обработки конфликтов. Вы можете установить механизм обработки
конфликтов либо в конструкторе:
parser = OptionParser(..., conflict_handler=handler)
или с отдельным вызовом:
parser.set_conflict_handler(handler)
Доступные обработчики конфликтов:
"error"
(по умолчанию)- предположим, что конфликты опций являются ошибкой программирования, и поднимем
OptionConflictError
"resolve"
- разумно разрешать конфликты опций (см. ниже)
В качестве примера давайте определим OptionParser
,
интеллектуально разрешающий конфликты, и добавим к нему конфликтующие параметры:
parser = OptionParser(conflict_handler="resolve")
parser.add_option("-n", "--dry-run", ..., help="do no harm")
parser.add_option("-n", "--noisy", ..., help="be noisy")
В данный момент optparse
обнаруживает, что ранее добавленная опция уже
использует строку опции -n
. Поскольку conflict_handler
— это
"resolve"
, ситуация решается путём удаления -n
из списка строк
параметров предыдущего параметра. Теперь --dry-run
— единственный способ
для пользователя активировать эту опцию. Если пользователь попросит о помощи,
справочное сообщение отразит следующее:
Options:
--dry-run do no harm
...
-n, --noisy be noisy
Строки опций для ранее добавленной опции можно свести на нет, пока их не
останется, и у пользователя не будет возможности вызвать эту опцию из командной
строки. В этом случае optparse
полностью удаляет данный параметр,
поэтому он не отображается в тексте справки или где-либо ещё. Продолжение с
нашим существующим OptionParser:
parser.add_option("--dry-run", ..., help="new dry-run option")
На данный момент исходная опция -n
/--dry-run
больше недоступна, поэтому
optparse
удаляет её, оставляя данный текст справки:
Options:
...
-n, --noisy be noisy
--dry-run new dry-run option
Очистка
У экземпляров OptionParser есть несколько циклических ссылок. Это не должно быть
проблемой для сборщика мусора Python, но вы можете явно разорвать циклические
ссылки, вызвав destroy()
в вашем OptionParser, как только
вы закончите с ним. Это особенно полезно в долго работающих приложениях, где
графы больших объектов доступны из вашего OptionParser.
Другие методы
OptionParser поддерживает несколько других общедоступных методов:
-
OptionParser.
set_usage
(usage) Устанавливает строку использования в соответствии с правилами, рассмотренными выше для ключевого аргумента конструктора
usage
. ПередачаNone
устанавливает строку использования по умолчанию; используйтеoptparse.SUPPRESS_USAGE
, чтобы подавить сообщение об использовании.
-
OptionParser.
print_usage
(file=None) Распечатывает сообщение об использовании для текущей программы (
self.usage
) в file (стандартный вывод по умолчанию). Любое вхождение строки%prog
вself.usage
заменяется именем текущей программы. Ничего не делает, еслиself.usage
пуст или не определён.
-
OptionParser.
get_usage
() То же, что и
print_usage()
, но возвращает строку использования вместо её вывода.
-
OptionParser.
set_defaults
(dest=value, ...) Устанавливает значения по умолчанию сразу для нескольких назначений опций. Использование
set_defaults()
является предпочтительным способом установки значений по умолчанию для параметров, поскольку несколько параметров могут иметь одно и то же место назначения. Например, если несколько параметров «режима» задают одно и то же место назначения, любой из них может установить значение по умолчанию, и последний из них выигрывает:parser.add_option("--advanced", action="store_const", dest="mode", const="advanced", default="novice") # переопределено ниже parser.add_option("--novice", action="store_const", dest="mode", const="novice", default="advanced") # переопределяет вышеуказанную настройку
Чтобы избежать этой путаницы, используйте
set_defaults()
:parser.set_defaults(mode="advanced") parser.add_option("--advanced", action="store_const", dest="mode", const="advanced") parser.add_option("--novice", action="store_const", dest="mode", const="novice")
Опции обратных вызовов
Если встроенных действий и типов optparse
недостаточно для ваших нужд, у
вас есть два варианта: расширить optparse
или определить параметр
обратного вызова. Расширение optparse
является более общим, но
избыточным для многих простых случаев. Довольно часто простой обратный вызов —
это все, что вам нужно.
Есть два шага для определения опции обратного вызова:
- определяет сам параметр с помощью действия
"callback"
. - написать обратный вызов; это функция (или метод), принимающая как минимум четыре аргумента, как приведено ниже.
Определение опции обратного вызова
Как всегда, самый простой способ определить параметр обратного вызова —
использовать метод OptionParser.add_option()
. Помимо
action
, единственным обязательным атрибутом параметра,
является вызываемая функция callback
:
parser.add_option("-c", action="callback", callback=my_callback)
callback
— это функция (или другой вызываемый объект), поэтому вы должны
уже определить my_callback()
при создании этой опции обратного вызова. В
этом простом случае optparse
даже не знает, принимает ли -c
какие-либо аргументы, что обычно означает, что опция не принимает
аргументов, — простое присутствие -c
в командной строке — это всё,
что ему нужно знать. Однако в некоторых случаях нужно, чтобы
обратный вызов использовал произвольное количество аргументов командной строки.
Здесь написание обратных вызовов становится сложным; это будет рассмотрено позже в
данном разделе.
optparse
всегда передаёт четыре конкретных аргумента вашему обратному
вызову, и он будет передавать дополнительные аргументы, только если вы укажете
их через callback_args
и callback_kwargs
. Таким
образом, минимальная сигнатура функции обратного вызова равна:
def my_callback(option, opt, value, parser):
Четыре аргумента обратного вызова рассмотрены далее.
Существует несколько других атрибутов опции, которые вы можете указать при определении опции обратного вызова:
type
- имеет свое обычное значение: как и в случае действий
"store"
или"append"
, it указываетoptparse
использовать один аргумент и преобразовывает его вtype
. Вместо того чтобы хранить преобразованные значения в любом месте, тем не менее,optparse
передает его вашей функции обратного вызова. nargs
- также имеет свое обычное значение: если он указан и > 1, будет
optparse
использовать аргументыnargs
, каждый из которых должен быть конвертируемымtype
. Затем он передаёт кортеж преобразованных значений в ваш колбэк. callback_args
- кортеж дополнительных позиционных аргументов для передачи обратному вызову.
callback_kwargs
- словарь дополнительных ключевых аргументов для передачи обратному вызову.
Как вызываются обратные вызовы?
Все обратные вызовы вызываются следующим образом:
func(option, opt_str, value, parser, *args, **kwargs)
где:
option
- это экземпляр Option, вызывающий обратный вызов.
opt_str
- это строка параметра, видимая в командной строке, которая запускает обратный вызов.
(Если использовалась сокращенная длинная опция,
opt_str
будет полной каноническая строка опции —, например, если пользователь помещает--foo
в файл командной строки как аббревиатуру--foobar
, тогда будетopt_str
"--foobar"
.). value
- является аргументом этой опции, отображаемой в командной строке.
optparse
будет ожидать аргумент, только если установленtype
; будет типvalue
тип, подразумеваемый типом опции. Еслиtype
для этой опции естьNone
(аргумент не ожидается), тогдаvalue
будетNone
. Еслиnargs
> 1,value
будет кортежем значений соответствующего типа. parser
является экземпляром OptionParser, управляющим всем, в основном полезным, потому что можно получить доступ к другим интересным данным через его атрибуты экземпляра:
parser.largs
- текущий список оставшихся аргументов, т. е. израсходованные аргументы,
но не являются ни параметрами, ни аргументами параметров. Не стесняйтесь изменять
parser.largs
, например, добавив к нему дополнительные аргументы. (Данный список будетargs
, вторым возвращаемым значениемparse_args()
.) parser.rargs
- текущий список оставшихся аргументов, т. е. с
opt_str
и Удаленыvalue
(если применимо) и только аргументы, следующие за ними все ещё там. Не стесняйтесь изменятьparser.rargs
, например, потребляя больше аргументы. parser.values
- объект, в котором по умолчанию хранятся значения параметров (экземпляр
optparse.OptionValues). Это позволяет обратным вызовам использовать тот же механизм, что и метод обратного вызова
остальная часть
optparse
для хранения значений опций; вам не нужно возиться вокруг с глобальными переменными или замыканиями. Вы также можете получить доступ или изменить файл значения любых опций, уже встречавшихся в командной строке.
args
- представляет собой кортеж произвольных позиционных аргументов, передаваемых через класс
атрибута опции
callback_args
. kwargs
- представляет собой словарь произвольных ключевых аргументов, поставляемых через
callback_kwargs
.
Вызов ошибок в обратном вызове
Функция обратного вызова должна вызвать OptionValueError
, если есть
какие-либо проблемы с опцией или её аргументом(ами). optparse
перехватывает это и завершает программу, выводя сообщение об ошибке, которое вы
отправляете в stderr. Ваше сообщение должно быть четким, кратким, точным и
содержать указание на неисправный вариант. В противном случае пользователю
будет сложно понять, что он сделал не так.
Пример обратного вызова 1: тривиальный обратный вызов
Вот пример опции обратного вызова, которая не принимает аргументов и просто записывает, что опция была просмотрена:
def record_foo_seen(option, opt_str, value, parser):
parser.values.saw_foo = True
parser.add_option("--foo", action="callback", callback=record_foo_seen)
Конечно, вы можете сделать это с помощью действия "store_true"
.
Пример обратного вызова 2: проверка порядка опций
Вот немного более интересный пример: записывает тот факт, что -a
виден, но
вызывается исключение, если он идет после -b
в командной строке.
def check_order(option, opt_str, value, parser):
if parser.values.b:
raise OptionValueError("can't use -a after -b")
parser.values.a = 1
...
parser.add_option("-a", action="callback", callback=check_order)
parser.add_option("-b", action="store_true", dest="b")
Пример обратного вызова 3: проверить порядок опций (обобщенный)
Если вы хотите повторно использовать данный обратный вызов для нескольких
похожих опций (установить флаг, но вызвать исключение, если -b
уже был замечен),
над ним нужно немного поработать: сообщение об ошибке и флаг, который он
устанавливает, должны быть обобщены.
def check_order(option, opt_str, value, parser):
if parser.values.b:
raise OptionValueError("can't use %s after -b" % opt_str)
setattr(parser.values, option.dest, 1)
...
parser.add_option("-a", action="callback", callback=check_order, dest='a')
parser.add_option("-b", action="store_true", dest="b")
parser.add_option("-c", action="callback", callback=check_order, dest='c')
Пример обратного вызова 4: проверка произвольного условия
Конечно, вы можете поместить туда любое условие, — вы не ограничены проверкой значений уже определённых опций. Например, если у вас есть опции, которые не следует вызывать при полной луне, все, что вам нужно сделать, это
def check_moon(option, opt_str, value, parser):
if is_moon_full():
raise OptionValueError("%s option invalid when moon is full"
% opt_str)
setattr(parser.values, option.dest, 1)
...
parser.add_option("--foo",
action="callback", callback=check_moon, dest="foo")
(Определение is_moon_full()
оставлено читателю в качестве упражнения.)
Пример обратного вызова 5: фиксированные аргументы
Все становится немного интереснее, когда вы определяете параметры обратного
вызова, принимающие фиксированное количество аргументов. Указание того,
что опция обратного вызова принимает аргументы, аналогично определению опции
"store"
или "append"
: если вы определяете type
, то
опция принимает один аргумент, преобразованный в данный тип;
если вы дополнительно определите nargs
, то опция принимает
аргументы nargs
.
Вот пример, повторяющий стандартное действие "store"
:
def store_value(option, opt_str, value, parser):
setattr(parser.values, option.dest, value)
...
parser.add_option("--foo",
action="callback", callback=store_value,
type="int", nargs=3, dest="foo")
Обратите внимание, что optparse
позаботится о том, чтобы использовать 3
аргумента и преобразовывает их в целые числа для вас; все, что вам нужно
сделать, это сохранить их. (Или что-то ещё; очевидно, вам не нужен обратный
вызов для этого примера.)
Пример обратного вызова 6: переменные аргументы
Когда вы хотите, чтобы опция принимала переменное количество аргументов, все
усложняется. В этом случае вы должны написать обратный вызов, т. к.
optparse
не предоставляет для него никаких встроенных возможностей. И
вам придется иметь дело с некоторыми сложностями обычного парсинга командной
строки Unix, с которыми optparse
обычно справляется за вас. В частности,
обратные вызовы должны реализовывать обычные правила для простых аргументов
--
и -
:
- либо
--
, либо-
могут быть аргументами опции. - голый
--
(если не аргумент какой-либо опции): останавливает обработку командной строки и отбросить--
. - голый
-
(если не аргумент какой-либо опции): останавливает обработку командной строки, но сохраняет-
(добавить его кparser.largs
).
Если вам нужна опция, принимающая переменное количество аргументов, есть
несколько тонких и каверзных проблем, о которых нужно беспокоиться. Точная
выбранная вами реализация, будет зависеть от того, какие компромиссы вы
готовы сделать для своего приложения (именно поэтому optparse
не
поддерживает такие вещи напрямую).
Тем не менее, вот попытка обратного вызова для опции с переменными аргументами:
def vararg_callback(option, opt_str, value, parser):
assert value is None
value = []
def floatable(str):
try:
float(str)
return True
except ValueError:
return False
for arg in parser.rargs:
# остановиться на --foo подобных опциях
if arg[:2] == "--" and len(arg) > 2:
break
# остановиться на -a, но не на -3 или -3.0
if arg[:1] == "-" and len(arg) > 1 and not floatable(arg):
break
value.append(arg)
del parser.rargs[:len(value)]
setattr(parser.values, option.dest, value)
...
parser.add_option("-c", "--callback", dest="vararg_attr",
action="callback", callback=vararg_callback)
Расширение optparse
Поскольку двумя основными определяющими факторами в том, как optparse
интерпретирует параметры командной строки, являются действие и тип каждого
параметра, наиболее вероятным направлением расширения является добавление новых
действий и новых типов.
Добавление новых типов
Чтобы добавить новые типы, вам нужно определить свой собственный подкласс
класса optparse
Option
. Данный класс имеет пару атрибутов,
определяющих типы optparse
: TYPES
и
TYPE_CHECKER
.
-
Option.
TYPES
Кортеж имён типов; в своём подклассе просто определяет новый кортеж
TYPES
, основанный на стандартном.
-
Option.
TYPE_CHECKER
Словарь, отображающий имена типов на функции проверки типов. Функция проверки типов имеет следующую сигнатуру:
def check_mytype(option, opt, value)
где
option
— экземплярOption
,opt
— строка параметра (например,-f
), аvalue
— строка из командной строки, которую необходимо проверить и преобразовывает в нужный тип.check_mytype()
должен возвращать объект гипотетического типаmytype
. Значение, возвращаемое функцией проверки типов, попадет в экземпляр OptionValues, возвращённыйOptionParser.parse_args()
, или будет передано обратному вызову в качестве параметраvalue
.Ваша функция проверки типов должна вызывать
OptionValueError
, если она сталкивается с какими-либо проблемами.OptionValueError
принимает один строковый аргумент, передаваемый как есть методуerror()
OptionParser
, который, в свою очередь, добавляет имя программы и строку"error:"
и выводит все в stderr перед завершением процесса.
Вот глупый пример, демонстрирующий добавление типа параметра "complex"
для
парсинга комплексных чисел в стиле Python в командной строке. (Это ещё глупее,
чем раньше, потому что в optparse
1.3 добавлена встроенная поддержка
комплексных чисел, но это неважно.)
Во-первых, необходимый импорт:
from copy import copy
from optparse import Option, OptionValueError
Сначала вам нужно определить средство проверки типов, т. к. оно упоминается
позже (в атрибуте класса TYPE_CHECKER
вашего подкласса
Option):
def check_complex(option, opt, value):
try:
return complex(value)
except ValueError:
raise OptionValueError(
"option %s: invalid complex value: %r" % (opt, value))
Наконец, подкласс Option:
class MyOption (Option):
TYPES = Option.TYPES + ("complex",)
TYPE_CHECKER = copy(Option.TYPE_CHECKER)
TYPE_CHECKER["complex"] = check_complex
(Если бы мы не сделали copy()
из Option.TYPE_CHECKER
, мы бы в
конечном итоге изменили атрибут TYPE_CHECKER
класса Option
optparse
. Поскольку это Python, ничто не мешает вам сделать это, кроме
хороших манер и здравого смысла.)
Вот и все! Теперь вы можете написать сценарий, использующий новый тип
параметра, как и любой другой сценарий на основе optparse
, за
исключением того, что вы должны указать OptionParser использовать
MyOption вместо Option:
parser = OptionParser(option_class=MyOption)
parser.add_option("-c", type="complex")
В качестве альтернативы вы можете создать свой список опций и
передать его в OptionParser; если вы не используете add_option()
вышеописанным способом, вам не нужно указывать OptionParser, какой класс
параметров использовать:
option_list = [MyOption("-c", action="store", type="complex", dest="c")]
parser = OptionParser(option_list=option_list)
Добавление новых действий
Добавление новых действий немного сложнее, потому что вы должны понимать, что
у optparse
есть несколько классификаций действий:
- «store» действия
- действия, в результате которых
optparse
сохраняет значение атрибута текущий экземпляр OptionValues; для данных опций требуется кодdest
атрибут, переданный конструктору Option. - «typed» действия
- действия, принимающие значение из командной строки и ожидающее, что оно будет иметь значение
определённого вида; вернее, строка преобразуемая в определённый тип.
Для данных параметров требуется атрибут
type
для параметра конструктора.
Это перекрывающиеся множества: некоторые действия «store» по умолчанию —
"store"
, "store_const"
, "append"
и "count"
, а «typed»
действия по умолчанию — "store"
, "append"
и "callback"
.
Когда добавляется действие, то необходимо классифицировать его, перечислив его по крайней мере в одном из следующих атрибутов класса Option (все это списки строк):
-
Option.
ACTIONS
Все действия должны быть перечислены в ACTIONS.
-
Option.
STORE_ACTIONS
Здесь дополнительно перечислены действия «store».
-
Option.
TYPED_ACTIONS
Здесь дополнительно перечислены «typed» действия.
-
Option.
ALWAYS_TYPED_ACTIONS
Всегда принимающие тип действия (т. е. чьи параметры всегда принимают значение), дополнительно перечислены здесь. Единственным эффектом этого является то, что
optparse
назначает тип по умолчанию,"string"
, параметрам без явного типа, действие которых указано вALWAYS_TYPED_ACTIONS
.
Чтобы фактически реализовать ваше новое действие, вы должны переопределить
метод take_action()
Option и добавить случай, распознающий ваше
действие.
Например, давайте добавим действие "extend"
. Это похоже на стандартное
действие "append"
, но вместо того, чтобы брать одно значение из командной
строки и добавлять его в существующий список, "extend"
будет принимать
несколько значений в одной строке с разделителями-запятыми и расширять ими
существующий список. Т. е., если --names
является опцией "extend"
типа
"string"
, командная строка
--names=foo,bar --names blah --names ding,dong
приведёт к списку:
["foo", "bar", "blah", "ding", "dong"]
Снова мы определяем подкласс Option:
class MyOption(Option):
ACTIONS = Option.ACTIONS + ("extend",)
STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",)
def take_action(self, action, dest, opt, value, values, parser):
if action == "extend":
lvalue = value.split(",")
values.ensure_value(dest, []).extend(lvalue)
else:
Option.take_action(
self, action, dest, opt, value, values, parser)
Особенности примечания:
"extend"
ожидает значение в командной строке и где-то сохраняет это значение, поэтому оно входит как вSTORE_ACTIONS
, так и вTYPED_ACTIONS
.чтобы гарантировать, что
optparse
назначает тип"string"
по умолчанию действиям"extend"
, мы также помещаем действие"extend"
вALWAYS_TYPED_ACTIONS
.MyOption.take_action()
реализует только это одно новое действие и передает управление обратноOption.take_action()
для стандартных действийoptparse
.values
— это экземпляр класса optparse_parser.Values, предоставляющий очень полезный методensure_value()
.ensure_value()
по сути являетсяgetattr()
с предохранительным клапаном; он вызывается как:values.ensure_value(attr, value)
Если атрибут
attr
дляvalues
не существует или имеет значениеNone
, то verify_value() сначала устанавливает для него значениеvalue
, а затем возвращает «value». Это очень удобно для таких действий, как"extend"
,"append"
и"count"
, накапливающий данные в переменной и ожидают, что эта переменная будет определённого типа (список для первых двух, целое число для последнего). Использованиеensure_value()
означает, что сценариям, использующим ваше действие, не нужно беспокоиться об установке значения по умолчанию для рассматриваемых пунктов назначения параметров; они могут просто оставить значение по умолчанию, т. к.None
иensure_value()
позаботятся о том, чтобы сделать это правильно, когда это необходимо.