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, созданный с помощью optparse

args

оставшиеся позиционные аргументы после обработки всех параметров

Чаще всего не указывается ни один из аргументов ключевого слова. Если вы указываете 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. If nargs > 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_args option.

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

Вызывается, если в командной строке передан неоднозначный параметр.

Вернуться на верх