optparse
— Парсер для опций командной строки¶
Исходный код: Lib/optparse.py.
Не рекомендуется, начиная с версии 3.2: Модуль optparse
является устаревшим и не будет развиваться дальше; развитие будет продолжено с модулем argparse
.
optparse
- это более удобная, гибкая и мощная библиотека для разбора опций командной строки, чем старый модуль getopt
. optparse
использует более декларативный стиль разбора командной строки: вы создаете экземпляр OptionParser
, заполняете его опциями и разбираете командную строку. optparse
позволяет пользователям указывать опции в обычном синтаксисе GNU/POSIX и дополнительно генерирует для вас сообщения об использовании и справку.
Вот пример использования optparse
в простом сценарии:
from optparse import OptionParser
...
parser = OptionParser()
parser.add_option("-f", "--file", dest="filename",
help="write report to FILE", metavar="FILE")
parser.add_option("-q", "--quiet",
action="store_false", dest="verbose", default=True,
help="don't print status messages to stdout")
(options, args) = parser.parse_args()
С помощью этих нескольких строк кода пользователи вашего скрипта теперь могут делать «обычные вещи» в командной строке, например:
<yourscript> --file=outfile -q
По мере разбора командной строки optparse
устанавливает атрибуты объекта options
, возвращаемого parse_args()
, на основе значений, введенных пользователем из командной строки. Когда parse_args()
возвращается после разбора этой командной строки, options.filename
будет "outfile"
, а options.verbose
будет False
. optparse
поддерживает как длинные, так и короткие опции, позволяет объединять короткие опции вместе, а также позволяет связывать опции с их аргументами различными способами. Таким образом, все следующие командные строки эквивалентны приведенному выше примеру:
<yourscript> -f outfile --quiet
<yourscript> --quiet --file outfile
<yourscript> -q -foutfile
<yourscript> -qfoutfile
Кроме того, пользователи могут выполнить один из следующих пунктов:
<yourscript> -h
<yourscript> --help
и optparse
выведут краткую информацию о параметрах вашего сценария:
Usage: <yourscript> [options]
Options:
-h, --help show this help message and exit
-f FILE, --file=FILE write report to FILE
-q, --quiet don't print status messages to stdout
где значение yourscript определяется во время выполнения (обычно из sys.argv[0]
).
Справочная информация¶
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 отдельных частей информации, не имеет особого значения, каким образом* вы получите эту информацию от пользователя - большинство людей сдадутся и уйдут, прежде чем успешно запустят программу. Это относится к интерфейсу пользователя, будь то командная строка, конфигурационный файл или графический интерфейс: если вы предъявляете столько требований к пользователям, большинство из них просто сдадутся.
Короче говоря, постарайтесь свести к минимуму количество информации, которую пользователи должны предоставлять в обязательном порядке - используйте разумные значения по умолчанию, когда это возможно. Конечно, вы также хотите сделать свои программы достаточно гибкими. Для этого и существуют опции. Опять же, неважно, будут ли это записи в конфигурационном файле, виджеты в диалоге «Preferences» графического интерфейса или опции командной строки - чем больше опций вы реализуете, тем более гибкой будет ваша программа, и тем сложнее станет ее реализация. Слишком большая гибкость, конечно, имеет и недостатки; слишком большое количество опций может перегрузить пользователей и сделать ваш код гораздо более сложным для сопровождения.
Учебник¶
Хотя 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"
хранить постоянное значение
"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]
(Если вывод справки вызван опцией help, 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
) в file (по умолчанию 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
)Параграф текста справки, который будет напечатан после справки по опциям.
Наполнение синтаксического анализатора¶
Существует несколько способов заполнения синтаксического анализатора опциями. Предпочтительным является использование 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"
хранить постоянное значение
"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
, когда эта опция встречается в командной строке; доступные опции документированы 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
.
Стандартные действия опций¶
Различные действия с опциями имеют несколько разные требования и эффекты. Большинство действий имеют несколько соответствующих атрибутов опции, которые вы можете указать, чтобы направить поведение 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"
[required:const
; relevant:dest
]Значение
const
сохраняется вdest
.Пример:
parser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbose") parser.add_option("-v", "--verbose", action="store_const", const=1, dest="verbose") parser.add_option("--noisy", action="store_const", const=2, dest="verbose")
Если видно
--noisy
, тоoptparse
установитoptions.verbose = 2
"store_true"
[релевантно:dest
]Частный случай
"store_const"
, который сохраняетTrue
доdest
."store_false"
[релевантно:dest
]Как
"store_true"
, но хранитFalse
.Пример:
parser.add_option("--clobber", action="store_true", dest="clobber") parser.add_option("--no-clobber", action="store_false", dest="clobber")
"append"
[актуально:type
,dest
,nargs
,choices
].За опцией должен следовать аргумент, который добавляется к списку в
dest
. Если значение по умолчанию дляdest
не задано, пустой список создается автоматически, когдаoptparse
впервые встречает эту опцию в командной строке. Еслиnargs
> 1, используется несколько аргументов, и кортеж длиныnargs
добавляется кdest
.Значения по умолчанию для
type
иdest
такие же, как и для действия"store"
.Пример:
parser.add_option("-t", "--tracks", action="append", type="int")
Если в командной строке встречается
-t3
, тоoptparse
делает эквивалент:options.tracks = [] options.tracks.append(int("3"))
Если чуть позже появится
--tracks=4
, это означает:options.tracks.append(int("4"))
Действие
append
вызывает методappend
на текущем значении опции. Это означает, что любое указанное значение по умолчанию должно иметь методappend
. Это также означает, что если значение по умолчанию непустое, то элементы по умолчанию будут присутствовать в разобранном значении опции, а любые значения из командной строки будут добавлены после этих значений по умолчанию:>>> parser.add_option("--files", action="append", default=['~/.mypkg/defaults']) >>> opts, args = parser.parse_args(['--files', 'overrides.mypkg']) >>> opts.files ['~/.mypkg/defaults', 'overrides.mypkg']
"append_const"
[required:const
; relevant: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
, которая вызывается какЕсли для опции не задана строка
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. Обычно имеет значение, только если аргумент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
для хранения аргументов опции (по умолчанию: новый экземплярValues
) – если вы передадите существующий объект, параметры опции по умолчанию не будут инициализированы на нем
а возвращаемыми значениями являются
options
тот же объект, который был передан как
values
, или экземпляр optparse.Values, созданныйoptparse
.args
оставшиеся позиционные аргументы после обработки всех опций
Наиболее распространенным вариантом использования является предоставление ни одного из аргументов ключевого слова. Если вы передадите values
, оно будет модифицировано многократными вызовами setattr()
(примерно по одному на каждый аргумент опции, сохраненный в пункте назначения опции) и возвращено parse_args()
.
Если parse_args()
встречает какие-либо ошибки в списке аргументов, он вызывает метод OptionParser error()
с соответствующим сообщением об ошибке для конечного пользователя. В итоге ваш процесс завершается со статусом выхода 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)¶ Устанавливает, что синтаксический разбор не останавливается на первом неопциионе, позволяя перемежать переключатели с аргументами команды. Это поведение по умолчанию.
-
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 (по умолчанию 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
).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
обычно обрабатывает за вас. В частности, обратные вызовы должны реализовать обычные правила для голых аргументов --
и -
:
Ситуация осложняется, когда вы хотите, чтобы опция принимала переменное количество аргументов. Для этого случая вы должны написать обратный вызов, поскольку
--
не предоставляет для этого никаких встроенных возможностей. И вам придется иметь дело с некоторыми тонкостями обычного разбора командной строки Unix, которые-
обычно обрабатывает за вас. В частности, обратные вызовы должны реализовать обычные правила для голых аргументов и :bare
--
(если не является аргументом какой-либо опции): остановить обработку командной строки и отбросить--
.bare
-
(если не является аргументом какой-либо опции): остановить обработку командной строки, но сохранить-
(добавить его к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
.Ваша функция проверки типов должна выдать сообщение
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"
в конструкторе Option.
Когда вы добавляете действие, вам необходимо классифицировать его, включив его хотя бы в один из следующих атрибутов класса Option (все они являются списками строк):
-
Option.
ACTIONS
¶ Все действия должны быть перечислены в разделе ACTIONS.
-
Option.
STORE_ACTIONS
¶ Действия «хранить» дополнительно перечислены здесь.
-
Option.
TYPED_ACTIONS
¶ «Набранные» действия дополнительно перечислены здесь.
-
Option.
ALWAYS_TYPED_ACTIONS
¶ Действия, которые всегда принимают тип (т.е. чьи опции всегда принимают значение), дополнительно перечислены здесь. Единственный эффект этого заключается в том, что
optparse
присваивает тип по умолчанию,"string"
, опциям без явного типа, действие которых перечислено вALWAYS_TYPED_ACTIONS
.
Для того чтобы действительно реализовать ваше новое действие, вы должны переопределить метод Option take_action()
и добавить case, который распознает ваше действие.
Например, добавим действие "extend"
. Оно похоже на стандартное действие "append"
, но вместо того, чтобы принимать одно значение из командной строки и добавлять его к существующему списку, "extend"
будет принимать несколько значений в одной строке, разделенной запятыми, и расширять ими существующий список. То есть, если --names
является опцией "extend"
типа "string"
, то командная строка
--names=foo,bar --names blah --names ding,dong
приведет к списку
["foo", "bar", "blah", "ding", "dong"]
И снова мы определяем подкласс Option:
class MyOption(Option):
ACTIONS = Option.ACTIONS + ("extend",)
STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",)
def take_action(self, action, dest, opt, value, values, parser):
if action == "extend":
lvalue = value.split(",")
values.ensure_value(dest, []).extend(lvalue)
else:
Option.take_action(
self, action, dest, opt, value, values, parser)
Особенности:
"extend"
как ожидает значение в командной строке, так и сохраняет его где-то, поэтому оно входит и вSTORE_ACTIONS
, и вTYPED_ACTIONS
.чтобы убедиться, что
optparse
присваивает действиям"string"
тип по умолчанию"extend"
, мы помещаем действие"extend"
также вALWAYS_TYPED_ACTIONS
.MyOption.take_action()
реализует только это новое действие, и передает управление обратноOption.take_action()
для стандартных действийoptparse
.values
является экземпляром класса optparse_parser.Values, который предоставляет очень полезный методensure_value()
.ensure_value()
по сути являетсяgetattr()
с предохранительным клапаном; он вызывается какvalues.ensure_value(attr, value)
Если атрибут
attr
вvalues
не существует или равенNone
, то функция ensure_value() сначала устанавливает его вvalue
, а затем возвращает „значение“. Это очень удобно для таких действий, как"extend"
,"append"
и"count"
, которые накапливают данные в переменной и ожидают, что эта переменная будет определенного типа (список для первых двух, целое число для последнего). Использованиеensure_value()
означает, что сценариям, использующим ваше действие, не нужно беспокоиться об установке значения по умолчанию для рассматриваемых опциональных направлений; они могут просто оставить значение по умолчаниюNone
, аensure_value()
позаботится о том, чтобы все было правильно, когда это потребуется.