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 также используется термин «word».Иногда желательно заменить список аргументов, отличный от
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 или определенные устаревшие платформы (например, виртуальные машины, 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 является аргументом option. foo и bar являются позиционными аргументами.
Для чего существуют варианты?¶
Опции используются для предоставления дополнительной информации для настройки выполнения программы. В случае, если это не совсем понятно, опции обычно являются необязательными. Программа должна нормально работать без каких-либо опций. (Выберите произвольную программу из наборов инструментов Unix или GNU. Может ли он работать вообще без каких-либо опций и при этом иметь смысл? Основными исключениями являются find, tar, и dd—, которые все являются странными мутантами, которые были справедливо раскритикованы за их нестандартный синтаксис и запутанные интерфейсы.)
Многие люди хотят, чтобы в их программах были «обязательные опции». Подумайте об этом. Если это требуется, то это необязательно! Если есть какая-то информация, которая абсолютно необходима вашей программе для успешного выполнения, то для этого и нужны позиционные аргументы.
В качестве примера хорошего дизайна интерфейса командной строки рассмотрим скромную утилиту cp для копирования файлов. Не имеет особого смысла пытаться копировать файлы, не указав место назначения и хотя бы один источник. Следовательно, cp завершается ошибкой, если вы запускаете его без аргументов. Однако он обладает гибким и полезным синтаксисом, который вообще не требует каких-либо настроек:
cp SOURCE DEST
cp SOURCE ... DEST-DIR
С помощью этого можно добиться довольно многого. Большинство реализаций cp предоставляют множество опций для точной настройки способа копирования файлов: вы можете сохранить режим и время модификации, не переходить по символическим ссылкам, спрашивать, прежде чем удалять существующие файлы, и т.д. Но ничто из этого не отвлекает от основной задачи cp, которая заключается в копировании либо одного файла в другой, либо нескольких файлов в другой каталог.
Для чего нужны позиционные аргументы?¶
Позиционные аргументы предназначены для тех фрагментов информации, которые абсолютно необходимы вашей программе для выполнения.
К хорошему пользовательскому интерфейсу должно быть как можно меньше абсолютных требований. Если для успешной работы вашей программе требуется 17 различных фрагментов информации, не имеет большого значения, как вы получите эту информацию от пользователя - большинство людей сдадутся и уйдут, не успев успешно запустить программу. Это применимо независимо от того, является ли пользовательский интерфейс командной строкой, файлом конфигурации или графическим интерфейсом: если вы предъявляете к своим пользователям так много требований, большинство из них просто откажутся от них.
Короче говоря, постарайтесь свести к минимуму объем информации, которую пользователи обязаны предоставлять в обязательном порядке, - по возможности используйте разумные значения по умолчанию. Конечно, вы также хотите сделать свои программы достаточно гибкими. Для этого и существуют опции. Опять же, не имеет значения, являются ли они записями в конфигурационном файле, виджетами в диалоговом окне «Настройки» графического интерфейса или параметрами командной строки - чем больше параметров вы реализуете, тем более гибкой становится ваша программа и тем сложнее становится ее реализация. Конечно, чрезмерная гибкость также имеет свои недостатки; слишком большое количество опций может перегружать пользователей и значительно усложнять обслуживание вашего кода.
Руководство¶
Несмотря на то, что optparse является достаточно гибким и мощным, в большинстве случаев его также просто использовать. В этом разделе рассматриваются шаблоны кода, которые являются общими для любой программы, основанной на optparse.
Сначала вам нужно импортировать класс OptionParser; затем, в начале основной программы, создайте экземпляр OptionParser:
from optparse import OptionParser
...
parser = OptionParser()
Затем вы можете приступить к определению параметров. Основной синтаксис таков:
parser.add_option(opt_str, ...,
attr=value, ...)
Каждый параметр имеет одну или несколько строк параметров, таких как -f или --file, и несколько атрибутов параметров, которые сообщают optparse чего ожидать и что делать, когда он встречает этот параметр в командной строке.
Как правило, каждый параметр будет содержать одну короткую строку параметров и одну длинную строку параметров, например:
parser.add_option("-f", "--file", ...)
Вы можете задать столько коротких строк параметров и столько длинных строк параметров, сколько захотите (включая ноль), при условии, что в целом имеется хотя бы одна строка параметров.
Строки параметров, передаваемые в OptionParser.add_option(), фактически являются метками для параметра, определенного этим вызовом. Для краткости мы будем часто ссылаться на «поиск параметра» в командной строке; на самом деле, optparse обнаруживает «строки параметров» и ищет в них параметры.
Как только все ваши параметры будут определены, попросите optparse проанализировать командную строку вашей программы:
(options, args) = parser.parse_args()
(Если хотите, вы можете передать пользовательский список аргументов в parse_args(), но это редко бывает необходимо: по умолчанию используется sys.argv[1:].)
parse_args() возвращает два значения:
options, объект, содержащий значения для всех ваших параметров—например, если--fileпринимает единственный строковый аргумент, тоoptions.fileбудет именем файла, указанным пользователем, илиNoneесли пользователь не указал эту опциюargs, список позиционных аргументов, оставшихся после разбора параметров
В этом разделе руководства рассматриваются только четыре наиболее важных атрибута опции: action, type, dest (пункт назначения) и help. Из них action является наиболее фундаментальным.
Понимание действий по выбору¶
Действия указывают optparse, что делать, когда в командной строке появляется опция. Существует фиксированный набор действий, жестко заданный в optparse; добавление новых действий - это расширенная тема, рассмотренная в разделе Расширение optparse. В большинстве действий optparse указывается, что необходимо сохранить значение в некоторой переменной - например, взять строку из командной строки и сохранить ее в атрибуте options.
Если вы не укажете действие параметра, то по умолчанию будет установлено значение optparse store.
Акция в магазине¶
Наиболее распространенным вариантом действия является store, который указывает optparse принять следующий аргумент (или оставшуюся часть текущего аргумента), убедиться, что он имеет правильный тип, и сохранить его в выбранном вами месте назначения.
Например:
parser.add_option("-f", "--file",
action="store", type="string", dest="filename")
Теперь давайте создадим фальшивую командную строку и попросим optparse разобрать ее:
args = ["-f", "foo.txt"]
(options, args) = parser.parse_args(args)
Когда optparse видит строку параметра -f, он использует следующий аргумент, foo.txt, и сохраняет его в options.filename. Итак, после этого вызова parse_args(), options.filename будет "foo.txt".
Некоторые другие типы параметров, поддерживаемые optparse, - это int и float. Вот параметр, который ожидает целочисленный аргумент:
parser.add_option("-n", type="int", dest="num")
Обратите внимание, что у этого параметра нет длинной строки параметров, что вполне приемлемо. Кроме того, нет явного действия, поскольку значение по умолчанию равно store.
Давайте разберем еще одну фальшивую командную строку. На этот раз мы противопоставим аргумент option аргументу option: поскольку -n42 (один аргумент) эквивалентен -n 42 (два аргумента), код
(options, args) = parser.parse_args(["-n42"])
print(options.num)
выведет 42.
Если вы не укажете тип, то optparse будет означать string. В сочетании с тем фактом, что действие по умолчанию равно store, это означает, что наш первый пример может быть намного короче:
parser.add_option("-f", "--file", dest="filename")
Если вы не указываете пункт назначения, optparse определяет разумное значение по умолчанию из строк параметров: если первая длинная строка параметров равна --foo-bar, то пункт назначения по умолчанию равен foo_bar. Если длинных строк параметров нет, optparse просматривает первую короткую строку параметров: по умолчанию для -f используется f.
optparse также включает встроенный тип complex. Добавление типов описано в разделе Расширение optparse.
Обработка логических параметров (флагов)¶
Опции флажка -присваивать переменной значение true или false при отображении определенного параметра - довольно распространены. optparse поддерживает их двумя отдельными действиями: store_true и store_false. Например, у вас может быть флаг verbose, который включается с помощью -v и выключается с помощью -q:
parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose")
Здесь у нас есть два разных варианта с одинаковым назначением, что вполне нормально. (Это просто означает, что вы должны быть немного осторожны при установке значений по умолчанию —смотрите ниже.)
Когда optparse встречается с -v в командной строке, для options.verbose устанавливается значение True; при обнаружении -q, options.verbose устанавливается значение False.
Другие действия¶
Некоторые другие действия, поддерживаемые optparse, включают:
"store_const"сохраните постоянное значение, заданное с помощью
Option.const"append"добавьте аргумент этого параметра в список
"count"увеличьте счетчик на единицу
"callback"вызов указанной функции
Они описаны в разделе Справочное руководство и разделе Опция обратного вызова.
Значения по умолчанию¶
Все приведенные выше примеры включают установку некоторой переменной («назначения»), когда отображаются определенные параметры командной строки. Что произойдет, если эти параметры никогда не отображаются? Поскольку мы не указали значения по умолчанию, все они имеют значение None. Обычно это нормально, но иногда требуется больший контроль. optparse позволяет указать значение по умолчанию для каждого пункта назначения, которое присваивается перед анализом командной строки.
Сначала рассмотрим подробный / тихий пример. Если мы хотим, чтобы для 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()
Как и прежде, учитывается последнее значение, указанное для данного параметра destination. Для наглядности попробуйте использовать тот или иной метод установки значений по умолчанию, а не оба сразу.
Создание справки¶
Возможность 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в строке usage до названия текущей программы, т.е.os.path.basename(sys.argv[0]). Затем расширенная строка выводится перед подробной справкой по параметрам.Если вы не указываете строку использования,
optparseиспользует простое, но разумное значение по умолчанию:"Usage: %prog [options]", что нормально, если ваш скрипт не принимает никаких позиционных аргументов.каждая опция определяет строку справки и не заботится о переносе строк—
optparseзаботится о переносе строк и о том, чтобы вывод справки выглядел хорошо.параметры, которые принимают значение, указывают на этот факт в автоматически сгенерированном справочном сообщении, например, для параметра «режим»:
-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)¶
где
синтаксический анализатор - это
OptionParserэкземпляр, в который будет вставлена группаназвание - это название группы
необязательное описание - это подробное описание группы
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) в файл (стандартный вывод по умолчанию). Как и в случае с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 обрабатывает ошибку одинаково: выводит сообщение об использовании программы и сообщение об ошибке в формате standard error и завершает работу со статусом ошибки 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выводит строку usage, она расширяется от%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.Опция)Класс, который будет использоваться при добавлении параметров в синтаксический анализатор в
add_option().version(по умолчанию:None)Строка версии для печати, когда пользователь указывает параметр версии. Если вы указываете значение true для
version,optparse, автоматически добавляется параметр версии с единственной строкой параметров--version. Подстрока%progраскрывается так же, как и дляusage.conflict_handler(по умолчанию:"error")Указывает, что делать, когда в синтаксический анализатор добавляются параметры с конфликтующими строками параметров; смотрите раздел Конфликты между вариантами.
description(по умолчанию:None)Абзац текста, содержащий краткий обзор вашей программы.
optparseпереформатируйте этот абзац, чтобы он соответствовал текущей ширине терминала, и распечатайте его, когда пользователь запросит справку (послеusage, но перед списком опций).formatter(по умолчанию: новыйIndentedHelpFormatter)Экземпляр optparse.HelpFormatter, который будет использоваться для печати текста справки.
optparseпредоставляет два конкретных класса для этой цели: IndentedHelpFormatter и TitledHelpFormatter.add_help_option(по умолчанию:True)Если значение равно true,
optparseдобавит параметр справки (со строками параметров-hи--help) в синтаксический анализатор.progСтрока, используемая при расширении
%progвusageиversionвместоos.path.basename(sys.argv[0]).epilog(по умолчанию:None)Абзац текста справки для печати после опции help.
Заполнение анализатора¶
Существует несколько способов заполнить синтаксический анализатор параметрами. Предпочтительный способ - использовать OptionParser.add_option(), как показано в разделе Руководство. add_option() может быть вызван одним из двух способов:
передайте ему экземпляр параметра (возвращаемый
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 напрямую.)
Определение параметров¶
Каждый экземпляр параметра представляет собой набор синонимичных строк параметров командной строки, например -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. Наиболее важным атрибутом option является
action, и он в значительной степени определяет, какие другие атрибуты являются релевантными или обязательными. Если вы передадите нерелевантные атрибуты опции или не сможете передать требуемые,optparseвызоветOptionErrorисключение, объясняющее вашу ошибку.Действие параметра определяет, что будет делать
optparseпри появлении этого параметра в командной строке. Стандартными действиями параметра, жестко заданными вoptparse, являются:"store"сохраните аргумент этого параметра (по умолчанию)
"store_const"сохраните постоянное значение, заданное с помощью
Option.const"store_true"хранить
True"store_false"хранить
False"append"добавьте аргумент этого параметра в список
"append_const"добавьте постоянное значение в список, предварительно заданный с помощью
Option.const"count"увеличьте счетчик на единицу
"callback"вызов указанной функции
"help"распечатайте сообщение об использовании, включая все опции и документацию к ним
(Если вы не указываете действие, по умолчанию используется значение
"store". Для этого действия вы также можете указать атрибутыtypeиdest; см. Стандартные действия с опциями.)
Как вы можете видеть, большинство действий связано с сохранением или обновлением значения где-либо. optparse для этого всегда создается специальный объект, обычно называемый options, который является экземпляром optparse.Values.
- class optparse.Values¶
Объект, содержащий проанализированные имена аргументов и значения в качестве атрибутов. Обычно создается вызовом при вызове
OptionParser.parse_args()и может быть переопределен пользовательским подклассом, передаваемым в аргумент values дляOptionParser.parse_args()(как описано в Разбор аргументов).
Аргументы параметра (и различные другие значения) хранятся как атрибуты этого объекта в соответствии с атрибутом параметра dest (назначение).
Например, когда вы звоните
parser.parse_args()
одна из первых вещей, которую делает optparse, - это создает объект options:
options = Values()
Если один из параметров в этом синтаксическом анализаторе определен с помощью
parser.add_option("-f", "--file", action="store", type="string", dest="filename")
и анализируемая командная строка включает в себя любое из следующих действий:
-ffoo
-f foo
--file=foo
--file foo
тогда optparse, увидев эту опцию, выполнит действие, эквивалентное
options.filename = "foo"
Атрибуты параметров type и dest почти так же важны, как и action, но только action имеет смысл для всех параметров.
Атрибуты опции¶
- class optparse.Option¶
Один аргумент командной строки с различными атрибутами, передаваемыми конструктору с помощью ключевого слова. Обычно создается с помощью
OptionParser.add_option(), а не напрямую, и может быть переопределен пользовательским классом с помощью аргумента option_class вOptionParser.
Следующие атрибуты опции могут быть переданы в качестве аргументов ключевого слова в OptionParser.add_option(). Если вы передаете атрибут опции, который не относится к конкретной опции, или не можете передать требуемый атрибут опции, optparse вызывает OptionError.
- Option.action¶
(по умолчанию:
"store")Определяет поведение
optparse, когда этот параметр отображается в командной строке; доступные параметры описаны в документации here.
- Option.type¶
(по умолчанию:
"string")Тип аргумента, ожидаемый для этого параметра (например,
"string"или"int"); доступные типы параметров задокументированы here.
- Option.dest¶
(по умолчанию: получено из строк параметров)
Если действие опции подразумевает запись или изменение значения где-либо, это указывает
optparse, куда его записать:destназывает атрибутoptionsобъекта, которыйoptparseсоздается при анализе командная строка.
- Option.default¶
Значение, которое следует использовать для назначения этого параметра, если этот параметр не отображается в командной строке. Смотрите также
OptionParser.set_defaults().
- Option.nargs¶
(по умолчанию: 1)
Сколько аргументов типа
typeдолжно быть использовано при отображении этой опции. Если > 1,optparseбудет сохранен набор значенийdest.
- Option.const¶
Для действий, которые сохраняют постоянное значение, необходимо сохранить постоянное значение.
- Option.choices¶
Для параметров типа
"choice"- список строк, из которых пользователь может выбирать.
- Option.callback¶
Для параметров с действием
"callback"вызываемый параметр вызывается при появлении этого параметра. Смотрите раздел Опция обратного вызова для получения подробной информации об аргументах, передаваемых вызываемому элементу.
- Option.callback_args¶
- Option.callback_kwargs¶
Дополнительные аргументы позиции и ключевого слова для передачи в
callbackпосле четырех стандартных аргументов обратного вызова.
- Option.help¶
Текст справки для печати для этого параметра отображается при перечислении всех доступных параметров после того, как пользователь введет параметр
help(например,--help). Если текст справки не указан, параметр будет указан без текста справки. Чтобы скрыть эту опцию, используйте специальное значениеoptparse.SUPPRESS_HELP.
- Option.metavar¶
(по умолчанию: получено из строк параметров)
Заменяет аргументы option, которые будут использоваться при печати текста справки. Пример приведен в разделе Руководство.
Стандартные действия с опциями¶
Различные действия с параметрами имеют несколько разные требования и эффекты. Большинство действий имеют несколько соответствующих атрибутов параметров, которые вы можете указать для управления поведением 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, используется несколько аргументов и кортеж длиной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"[требуется:const; актуально:dest]Аналогично
"store_const", но значениеconstдобавляется кdest; как и в случае с"append",destпо умолчанию используетсяNone, и при первом появлении параметра автоматически создается пустой список ."count"[актуально:dest]Увеличьте целое число, сохраненное в
dest. Если значение по умолчанию не указано,destустанавливается равным нулю перед первым увеличением.Пример:
parser.add_option("-v", action="count", dest="verbosity")
При первом появлении
-vв командной строкеoptparseвыполняет действие, эквивалентное:options.verbosity = 0 options.verbosity += 1
Каждое последующее появление
-vприводит кoptions.verbosity += 1
"callback"[обязательно:callback; актуально:type,nargs,callback_args,callback_kwargs]Вызовите функцию, указанную в
callback, которая вызывается какfunc(option, opt_str, value, parser, *args, **kwargs)
Смотрите раздел Опция обратного вызова для получения более подробной информации.
"help"Выводит полное справочное сообщение для всех параметров текущего анализатора параметров. Справочное сообщение создается из строки
usage, передаваемой в конструктор Optionparser, и строкиhelp, передаваемой в каждый параметр.Если для параметра не указана строка
help, он все равно будет указан в справочном сообщении. Чтобы полностью исключить параметр, используйте специальное значениеoptparse.SUPPRESS_HELP.optparseавтоматически добавляет параметрhelpко всем параметрам Optionparser, поэтому обычно вам не нужно его создавать.Пример:
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, в стандартный вывод будет выведено что-то вроде следующего справочного сообщения (при условии, что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. Как правило, это актуально только в том случае, если в конструктор OptionParser передан аргументversion. Как и в случае с параметрамиhelp, вы редко будете создавать параметрыversion, посколькуoptparseавтоматически добавляет их при необходимости.
Стандартные типы опций¶
optparse имеет пять встроенных типов опций: "string", "int", "choice", "float" и "complex". Если вам нужно добавить новые типы опций, смотрите раздел Расширение optparse.
Аргументы в string options никоим образом не проверяются и не преобразуются: текст в командной строке сохраняется в пункте назначения (или передается в callback) как есть.
Целочисленные аргументы (тип "int") обрабатываются следующим образом:
если число начинается с
0x, оно преобразуется в шестнадцатеричное числоесли число начинается с
0, оно преобразуется в восьмеричное числоесли число начинается с
0b, оно анализируется как двоичное числов противном случае число анализируется как десятичное число
Преобразование выполняется путем вызова int() с соответствующей базой (2, 8, 10 или 16). Если это не удается, то же самое происходит с optparse, хотя и с более полезным сообщением об ошибке.
Аргументы параметров "float" и "complex" преобразуются непосредственно в float() и complex() с аналогичной обработкой ошибок.
"choice" параметры являются подтипом параметров "string". Атрибут choices option (последовательность строк) определяет набор допустимых аргументов параметра. optparse.check_choice() сравнивает аргументы параметра, предоставленные пользователем, с этим основным списком и выдает OptionValueError, если указана недопустимая строка.
Разбор аргументов¶
Весь смысл создания и заполнения OptionParser заключается в вызове его метода parse_args().
- OptionParser.parse_args(args=None, values=None)¶
Проанализируйте параметры командной строки, найденные в args.
Входными параметрами являются
argsсписок аргументов для обработки (по умолчанию:
sys.argv[1:])valuesобъект
Valuesдля хранения аргументов параметра (по умолчанию: новый экземплярValues) - если вы укажете существующий объект, значения параметра по умолчанию не будут инициализированы для него
и возвращаемое значение представляет собой пару
(options, args), гдеoptionsтот же объект, который был передан как values, или экземпляр
optparse.Values, созданный с помощьюoptparseargsоставшиеся позиционные аргументы после обработки всех параметров
Чаще всего не указывается ни один из аргументов ключевого слова. Если вы указываете values, он будет изменен с помощью повторных вызовов setattr() (примерно по одному для каждого аргумента option, сохраненного в пункте назначения option) и возвращен с помощью 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)¶
Возвращает экземпляр параметра со строкой параметра 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) в файл (стандартный вывод по умолчанию). Любое появление строки%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это экземпляр опции, который вызывает обратный вызов
opt_strэто строка параметров, отображаемая в командной строке, которая запускает обратный вызов. (Если был использован сокращенный вариант long,
opt_strбудет полной, канонической строкой параметров—например, если пользователь вводит--fooв командной строке в качестве сокращения для--foobar, тоopt_strбудет"--foobar".)valueявляется аргументом для этой опции, отображаемым в командной строке.
optparseбудет ожидать аргумент только в том случае, если задано значениеtype; типvalueбудет соответствовать типу, указанному в параметре type. Еслиtypeдля этого параметра равноNone(аргумент не ожидается), тоvalueбудет равноNone. Ifnargs> 1,valueбудет представлять собой набор значений соответствующего типа.parserявляется ли экземпляр OptionParser управляющим всем этим, в основном полезным, потому что вы можете получить доступ к некоторым другим интересным данным через атрибуты его экземпляра:
parser.largsтекущий список оставшихся аргументов, т.е. аргументов, которые были использованы, но не являются ни параметрами, ни аргументами option. Не стесняйтесь изменять
parser.largs, например, добавляя к нему дополнительные аргументы. (Этот список станетargs, вторым возвращаемым значениемparse_args().)parser.rargsтекущий список оставшихся аргументов, т.е. с
opt_strиvalue(если применимо) удалены, и только аргументы, следующие за ними, все еще присутствуют. Не стесняйтесь изменятьparser.rargs, например, используя больше аргументов.parser.valuesобъект, в котором по умолчанию хранятся значения параметров (экземпляр optparse.Значения параметров). Это позволяет обратным вызовам использовать тот же механизм, что и остальные
optparseдля хранения значений параметров; вам не нужно возиться с глобальными параметрами или замыканиями. Вы также можете получить доступ к любым параметрам, уже имеющимся в командной строке, или изменить их значения.
argsпредставляет собой набор произвольных позиционных аргументов, предоставляемых с помощью атрибута
callback_argsoption.kwargsпредставляет собой словарь аргументов произвольного ключевого слова, передаваемых через
callback_kwargs.
Возникновение ошибок при обратном вызове¶
Функция обратного вызова должна вызвать OptionValueError, если есть какие-либо проблемы с параметром или его аргументами. optparse перехватывает это и завершает работу программы, выводя сообщение об ошибке, которое вы отправляете в stderr. Ваше сообщение должно быть ясным, кратким, аккуратным и содержать указание на неисправность. В противном случае пользователю будет трудно понять, что он сделал не так.
Пример обратного вызова 1: тривиальный обратный вызов¶
Вот пример параметра обратного вызова, который не принимает аргументов и просто записывает, что этот параметр был просмотрен:
def record_foo_seen(option, opt_str, value, parser):
parser.values.saw_foo = True
parser.add_option("--foo", action="callback", callback=record_foo_seen)
Конечно, вы могли бы сделать это с помощью действия "store_true".
Пример обратного вызова 2: проверьте порядок опций¶
Вот чуть более интересный пример: запишите в командной строке тот факт, что отображается -a, но если он появляется после -b, то это не сработает.
def check_order(option, opt_str, value, parser):
if parser.values.b:
raise OptionValueError("can't use -a after -b")
parser.values.a = 1
...
parser.add_option("-a", action="callback", callback=check_order)
parser.add_option("-b", action="store_true", dest="b")
Пример обратного вызова 3: проверка порядка опций (обобщенный)¶
Если вы хотите повторно использовать этот обратный вызов для нескольких аналогичных опций (установите флаг, но отключите его, если -b уже было замечено), с ним нужно немного поработать: сообщение об ошибке и флаг, который оно устанавливает, должны быть обобщены.
def check_order(option, opt_str, value, parser):
if parser.values.b:
raise OptionValueError("can't use %s after -b" % opt_str)
setattr(parser.values, option.dest, 1)
...
parser.add_option("-a", action="callback", callback=check_order, dest='a')
parser.add_option("-b", action="store_true", dest="b")
parser.add_option("-c", action="callback", callback=check_order, dest='c')
Пример обратного вызова 4: проверка произвольного условия¶
Конечно, вы можете задать любое условие - вы не ограничены проверкой значений уже определенных параметров. Например, если у вас есть параметры, которые не следует вызывать в полнолуние, все, что вам нужно сделать, это:
def check_moon(option, opt_str, value, parser):
if is_moon_full():
raise OptionValueError("%s option invalid when moon is full"
% opt_str)
setattr(parser.values, option.dest, 1)
...
parser.add_option("--foo",
action="callback", callback=check_moon, dest="foo")
(Определение is_moon_full() оставлено в качестве упражнения для читателя.)
Пример обратного вызова 5: фиксированные аргументы¶
Все становится немного интереснее, когда вы определяете параметры обратного вызова, которые принимают фиксированное количество аргументов. Указание того, что параметр обратного вызова принимает аргументы, аналогично определению параметра "store" или "append": если вы определяете type, то параметр принимает один аргумент, который должен быть преобразован в этот тип; если вы дополнительно определяете nargs, тогда параметр принимает nargs аргумента.
Вот пример, который просто имитирует стандартное действие "store":
def store_value(option, opt_str, value, parser):
setattr(parser.values, option.dest, value)
...
parser.add_option("--foo",
action="callback", callback=store_value,
type="int", nargs=3, dest="foo")
Обратите внимание, что optparse использует 3 аргумента и преобразует их в целые числа для вас; все, что вам нужно сделать, это сохранить их. (Или что-то еще; очевидно, что в этом примере обратный вызов вам не нужен.)
Пример обратного вызова 6: переменные аргументы¶
Ситуация усложняется, когда вы хотите, чтобы параметр принимал переменное количество аргументов. В этом случае вы должны написать обратный вызов, поскольку optparse не предоставляет для этого никаких встроенных возможностей. И вам придется иметь дело с некоторыми тонкостями обычного синтаксического анализа командной строки Unix, которые optparse обычно обрабатываются за вас. В частности, обратные вызовы должны реализовывать обычные правила для простых аргументов -- и -:
аргументами параметра могут быть либо
--, либо-просто
--(если это не аргумент для какой-либо опции): остановите обработку в командной строке и удалите--убрать
-(если это не аргумент для какой-либо опции): приостановить обработку в командной строке, но сохранить-(добавить его кparser.largs)
Если вам нужен параметр, который принимает переменное количество аргументов, есть несколько тонких и каверзных вопросов, о которых стоит беспокоиться. Точная реализация, которую вы выберете, будет зависеть от того, на какие компромиссы вы готовы пойти для своего приложения (именно поэтому optparse не поддерживает такого рода вещи напрямую).
Тем не менее, вот пример обратного вызова для опции с переменными аргументами:
def vararg_callback(option, opt_str, value, parser):
assert value is None
value = []
def floatable(str):
try:
float(str)
return True
except ValueError:
return False
for arg in parser.rargs:
# stop on --foo like options
if arg[:2] == "--" and len(arg) > 2:
break
# stop on -a, but not on -3 or -3.0
if arg[:1] == "-" and len(arg) > 1 and not floatable(arg):
break
value.append(arg)
del parser.rargs[:len(value)]
setattr(parser.values, option.dest, value)
...
parser.add_option("-c", "--callback", dest="vararg_attr",
action="callback", callback=vararg_callback)
Расширение optparse¶
Поскольку двумя основными факторами, влияющими на то, как optparse интерпретирует параметры командной строки, являются действие и тип каждой опции, наиболее вероятным направлением расширения является добавление новых действий и новых типов.
Добавление новых типов¶
Чтобы добавлять новые типы, вам нужно определить свой собственный подкласс класса optparse в Option. Этот класс имеет несколько атрибутов, которые определяют типы optparse: TYPES и TYPE_CHECKER.
- Option.TYPES¶
Кортеж с именами типов; в вашем подклассе просто определите новый кортеж
TYPES, основанный на стандартном.
- Option.TYPE_CHECKER¶
Словарь, отображающий имена типов в функции проверки типов. Функция проверки типов имеет следующую сигнатуру:
def check_mytype(option, opt, value)
где
option- этоOptionэкземпляр,opt- строка параметров (например,,-f), иvalue- строка из командной строки, которая должна быть проверена и преобразована в нужный вам тип.check_mytype()должен возвращать объект гипотетического типаmytype. Значение, возвращаемое функцией проверки типов, попадет в экземпляр OptionValues, возвращаемыйOptionParser.parse_args(), или будет передано в обратный вызов в качестве параметраvalue.Ваша функция проверки типов должна выдавать
OptionValueError, если она сталкивается с какими-либо проблемами.OptionValueErrorпринимает единственный строковый аргумент, который передается как есть методуOptionParser, который,error()в свою очередь, добавляет название программы и строку"error:"и выводит все в stderr перед завершением процесса.
Вот глупый пример, демонстрирующий добавление параметра "complex" для синтаксического анализа комплексных чисел в стиле Python в командной строке. (Это еще глупее, чем было раньше, потому что в optparse 1.3 добавлена встроенная поддержка комплексных чисел, но не обращайте внимания.)
Во-первых, необходимый импорт:
from copy import copy
from optparse import Option, OptionValueError
Сначала вам нужно определить свой инструмент проверки типов, поскольку он упоминается позже (в атрибуте TYPE_CHECKER class вашего подкласса 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, ничто не мешает вам делать это, кроме хороших манер и здравого смысла.)
Вот и все! Теперь вы можете написать скрипт, который использует новый тип option точно так же, как и любой другой скрипт на основе 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сохранению значения атрибута текущего экземпляра Option Values; для этих параметров требуется, чтобы атрибутdestбыл передан конструктору Option.- «типизированные» действия
действия, которые принимают значение из командной строки и ожидают, что оно будет определенного типа; или, скорее, строка, которая может быть преобразована в определенный тип. Для этих параметров требуется атрибут
typeв конструкторе параметров.
Это перекрывающиеся наборы: некоторые «сохраняемые» действия по умолчанию - это "store", "store_const", "append", и "count", в то время как «типизированные» действия по умолчанию - это "store", "append" и "callback".
Когда вы добавляете действие, вам необходимо классифицировать его, указав хотя бы в одном из следующих атрибутов класса Option (все они являются списками строк).:
- Option.ACTIONS¶
Все действия должны быть перечислены в разделе ДЕЙСТВИЯ.
- Option.STORE_ACTIONS¶
здесь также перечислены действия «сохранить».
- Option.TYPED_ACTIONS¶
здесь также перечислены «типизированные» действия.
- Option.ALWAYS_TYPED_ACTIONS¶
Здесь также перечислены действия, которые всегда имеют определенный тип (т.е. параметры которых всегда имеют значение). Единственным результатом этого является то, что
optparseприсваивает тип по умолчанию,"string", параметрам без явного типа, действие которых указано вALWAYS_TYPED_ACTIONS.
Чтобы на самом деле реализовать ваше новое действие, вы должны переопределить метод Option take_action() и добавить регистр, который распознает ваше действие.
Например, давайте добавим действие "extend". Это похоже на стандартное действие "append", но вместо того, чтобы брать одно значение из командной строки и добавлять его к существующему списку, "extend" будет принимать несколько значений в одной строке, разделенной запятыми, и расширять существующий список с помощью они. То есть, если --names является параметром "extend" типа "string", то командная строка
--names=foo,bar --names blah --names ding,dong
в результате получился бы список
["foo", "bar", "blah", "ding", "dong"]
Снова мы определяем подкласс Option:
class MyOption(Option):
ACTIONS = Option.ACTIONS + ("extend",)
STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",)
def take_action(self, action, dest, opt, value, values, parser):
if action == "extend":
lvalue = value.split(",")
values.ensure_value(dest, []).extend(lvalue)
else:
Option.take_action(
self, action, dest, opt, value, values, parser)
Примечательные особенности:
"extend"оба ожидают значение в командной строке и где-то сохраняют это значение, поэтому оно используется как вSTORE_ACTIONS, так и вTYPED_ACTIONS.чтобы гарантировать, что
optparseприсваивает тип по умолчанию"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()позаботятся о том, чтобы все было правильно когда это необходимо.
Исключения¶
- exception optparse.OptionError¶
Вызывается, если создается экземпляр
Optionс недопустимыми или несогласованными аргументами.
- exception optparse.OptionConflictError¶
Вызывается, если к
OptionParserдобавляются конфликтующие параметры.
- exception optparse.OptionValueError¶
Вызывается, если в командной строке обнаружено недопустимое значение параметра.
- exception optparse.BadOptionError¶
Возникает, если в командной строке передан недопустимый параметр.
- exception optparse.AmbiguousOptionError¶
Вызывается, если в командной строке передан неоднозначный параметр.