optparse — Парсер для параметров командной строки

Исходный код: Lib/optparse.py

Не рекомендуется, начиная с версии 3.2: Модуль optparse устарел и не будет разрабатываться в будующем; разработка будет продолжена в модуле argparse.


optparse является более удобной, гибкой и мощной библиотекой для парсинга параметров командной строки, чем старый модуль getopt. optparse использует более декларативный стиль парсинга командной строки: Вы создаете сущность OptionParser, заполняете его параметрами и разбираете командную строку. optparse позволяет пользователям задавать опции в обычном синтаксисе GNU/POSIX и дополнительно генерирует сообщения об использовании и справке для вас.

Вот пример использования optparse в простом сценарии:

from optparse import OptionParser
...
parser = OptionParser()
parser.add_option("-f", "--file", dest="filename",
                  help="write report to FILE", metavar="FILE")
parser.add_option("-q", "--quiet",
                  action="store_false", dest="verbose", default=True,
                  help="don't print status messages to stdout")

(options, args) = parser.parse_args()

С этими несколькими строками кода, пользователи вашего сценария теперь могут выполнять «обычную вещь» в командной строке, например:

<yourscript> --file=outfile -q

Поскольку он парсит командную строку, optparse устанавливает атрибуты возвращаемого объекта options parse_args() на основе снабженной пользователями командной строки значений. Когда parse_args() возвращает от парсинга эту командну строку, options.filename будет "outfile", и options.verbose будет False. optparse поддерживает как длинные, так и короткие опции, позволяет объединять короткие опции вместе и позволяет ассоциировать опции с их аргументами различными способами. Таким образом, все следующие командные строки эквивалентны приведенному выше примеру:

<yourscript> -f outfile --quiet
<yourscript> --quiet --file outfile
<yourscript> -q -foutfile
<yourscript> -qfoutfile

Кроме того, пользователи могут запускать одно из следующих действий:

<yourscript> -h
<yourscript> --help

и optparse распечатает краткое резюме опций сценария:

Usage: <yourscript> [options]

Options:
  -h, --help            show this help message and exit
  -f FILE, --file=FILE  write report to FILE
  -q, --quiet           don't print status messages to stdout

где значение yourscript определяется во время выполнения (обычно из sys.argv[0]).

Фон

optparse был явно разработан для поощрения создания программ с простыми, обычными интерфейсами командной строки. С этой целью он поддерживает только наиболее распространенный синтаксис командной строки и семантику традиционно используемый в Unix. Если вы не знакомы с этими соглашениями, прочитайте этот раздел, чтобы ознакомиться с ними.

Терминология

аргумент

строка, введенный в командной строке и переданный оболочкой в execl() или execv(). В Python аргументы являются элементами sys.argv[1:] (sys.argv[0] - имя исполняемой программы). Оболочки Unix также используют термин «слово».

Иногда желательно заменить список аргументов, отличный от sys.argv[1:], поэтому следует читать «аргумент» как «элемент sys.argv[1:] или какого-либо другого списка, предоставленного в качестве замены sys.argv[1:].».

опция

аргумент используемый для предоставления дополнительной информации для руководства или настройки выполнения программы. Существует множество различных синтаксисов для опций; традиционный Unix-синтаксис представляет собой дефис («-«), за которым следует одна буква, например -x или -F. Кроме того, традиционный синтаксис Unix позволяет объединить несколько параметров в один аргумент, например, -x -F эквивалентен -xF. Проект GNU ввел --, сопровождаемый серией отделенных от дефиса слов, например, --file или --dry-run. Это единственные два синтаксиса опций, предоставляемых optparse.

Некоторые другие синтаксисы опций, которые мир видел, включают в себя:

  • дефис, за которым следует несколько букв, например -pf (это не то же самое, что и несколько опций, объединенных в один аргумент)
  • дефис, за которым следует целое слово, например -file (это технически эквивалентно предыдущему синтаксису, но они обычно не отображаются в одной программе)
  • знак плюс, за которым следует одна буква или несколько букв, или слово, например +f, +rgb
  • косая черта, за которой следует буква или несколько букв, или слово, например /f, /file

Эти синтаксисы параметров не поддерживаются optparse, и они никогда не будут. Это намеренно: первые три нестандартны для любой среды, и последнее имеет смысл только в том случае, если вы нацелены исключительно на VMS, MS-DOS и/или Windows.

опциональный аргумент

аргумент который следует за опцией, тесно связан с этой опцией и используется из списка аргументов, когда эта опция является. При использовании параметра optparse аргументы могут находиться в отдельном аргументе от их параметра:

-f foo
--file foo

или включенный в тот же аргумент:

-ffoo
--file=foo

Обычно данный параметр принимает аргумент или нет. Многие люди хотят использовать функцию «необязательные аргументы», что означает, что некоторые опции будут принимать аргумент, если они его видят, и не будут, если они этого не сделают. Это несколько спорно, потому что делает парсинг неоднозначным: если -a принимает необязательный аргумент и -b - другой опции целиком, как мы интерпретируем -ab? из-за этой неоднозначности optparse не поддерживает эту функцию.

позиционный аргумент
оставшийся в списке аргументов после анализа параметров, т.е. после того, как параметры и их аргументы были проанализированы и удалены из списка аргументов.
обязательная опция
опция которая должен быть указана в командной строке; следует отметить, что в английском языке фраза «обязательная опция» является самопротиворечивой. optparse не мешает вам реализовать требуемые опции, но и не оказывает вам большой помощи в этом.

Например, рассмотрим гипотетическую командную строку:

prog -v --report report.txt foo bar

-v и --report - обе опции. Предполагая, что --report принимает один аргумент, report.txt является аргументом параметра. foo и bar являются позиционными аргументами.

Для чего нужны опции?

Опции - используются, чтобы предоставить дополнительную информацию, а также отрегулировать или настроить выполение программы. В случае, если было непонятно, опции обычно опциональны. Программа должна быть в состоянии работать просто прекрасно без каких-либо опций. (Выберите случайную программу из набора инструментов Unix или GNU. Может ли он работать без каких-либо опций вообще и по-прежнему имеет смысл? Основные исключения - find, tar и dd — все из которых являются мутантными однодолбами, которые были справедливо раскритикованы за нестандартный синтаксис и запутанные интерфейсы.)

Многие хотят, чтобы у их программ были «требуемые опции». Подумайте об этом. Если это требуется, то это не опционально! если есть часть информации, которая абсолютно необходима вашей программе для успешного выполнения, вот для чего нужны позиционные аргументы.

Как пример хорошего дизайна интерфейса командной строки, рассмотрите скромную полезность cp для копирования файлов. Нет большого смысла пытаться копировать файлы без указания места назначения и хотя бы одного источника. Следовательно, cp не удается, если запустить его без аргументов. Однако он имеет гибкий, полезный синтаксис, который вообще не требует каких-либо опций:

cp SOURCE DEST
cp SOURCE ... DEST-DIR

Ты можешь зайти довольно далеко с этим. Большинство cp реализаций предоставляют кучу опций, чтобы подстроить, как именно копируются файлы: можно сохранить режим и время модификации, избежать следующих симлинки, спросить перед клоббированием существующих файлов и т. д. Но ничто из этого не отвлекает от основной миссии cp, которая заключается в копировании либо одного файла в другой, либо нескольких файлов в другой каталог.

Для чего нужны позиционные аргументы?

Позиционные аргументы для тех частей информации, которые ваша программа абсолютно, положительно требует запуска.

Хороший пользовательский интерфейс должен иметь как можно меньше абсолютных требований. Если ваша программа требует 17 отличных сведений, чтобы бежать успешно, как не очень имеет значение, что вы получаете ту информацию от пользователя — большинство людей, сдастся и уйдет, прежде чем они успешно будут управлять программой. Это относится к тому, является ли пользовательский интерфейс командной строкой, конфигурационным файлом или графическим интерфейсом пользователя: если вы предъявляете к пользователям много требований, большинство из них просто сдадутся.

Короче говоря, попытайтесь минимизировать объем информации, что пользователи абсолютно обязаны поддерживать — использовать здравомыслящие по умолчаниюы, когда это возможно. Конечно, вы также хотите сделать ваши программы достаточно гибкими. Вот для чего нужны опции. Снова, не имеет значения, если они - записи в файле конфигурации, виджеты в «Предпочтительном» диалоге графический интерфейса пользователя или командная строка опций — больше опций, вы осуществляете, более гибкое, которое ваша программа, и более сложное, которым становится ее внедрение. Слишком большая гибкость имеет и недостатки, разумеется; слишком много опций может раздражать пользователей и значительно усложнить обслуживание вашего кода.

Учебник

В то время как optparse является достаточно гибким и мощным, это также просто использовать в большинстве случаев. В этом разделе рассматриваются шаблоны код, общие для любой программы на базе optparse.

Сначала необходимо импортировать класс OpterParser; тогда, рано в главной программе, создайте OptionParser сущность:

from optparse import OptionParser
...
parser = OptionParser()

Затем можно приступить к определению опций. Основной синтаксис::

parser.add_option(opt_str, ...,
                  attr=value, ...)

Каждый параметр имеет одну или несколько опций строки, таких как -f или --file, и несколько опций атрибуты, которые указывают optparse, что ожидать и что делать, когда он встречается с этим параметром в командной строке.

Как правило, каждая опция имеет одну короткую опцию строка и одну длинную опцию строка, например,:

parser.add_option("-f", "--file", ...)

Вы можете определить столько коротких опций строки и столько длинных опций строки, сколько хотите (включая ноль), пока есть по крайней мере одина опция строки в целом.

Опция, который строки передал к OptionParser.add_option(), являются эффективно этикетки для опции, определенного тем требованием. Для краткости часто ссылаемся на столкнувшись с опцией в командной строке; в действительности optparse сталкивается с опцией строки и ищет опции из них.

Как только все ваши опции определены, дают указание optparse распарсить командную строку вашей программы:

(options, args) = parser.parse_args()

(Если вы хотите, вы можете передать пользовательский список аргументов parse_args(), но это редко необходимо: по умолчанию он использует sys.argv[1:].)

parse_args() возвращает два значения:

  • options, объект, содержащий значения для всех ваших опций, т.е. если --file принимает один аргумент строка, то options.file будет имя файла, предоставленное пользователем, или None, если пользователь не предоставил этот параметр
  • args, список позиционных аргументов, оставшихся после параметров парсинг

В этом учебном разделе рассматриваются только четыре наиболее важных опций атрибуты: action, type, dest (пункт назначения) и help. Из них action - самый фундаментальный.

понимание действияй опций

Действия указывают optparse, что делать при обнаружении параметра в командной строке. Существует фиксированный набор действий, жестко закодированных в optparse; добавление новых действий - это расширенная тема, описанная в разделе Расширение optparse. Большинство действий велит optparse сохранить значение в каком-либо примере переменной — для, взять строка из командной строки и сохранить его в атрибут options.

Если действие параметра не указано, optparse по умолчанию принимает значение store.

Действие store

Наиболее распространенным действием опции является действие store, которое предписывает optparse взять следующий аргумент (или остаток текущего аргумента), убедиться, что он имеет правильный тип, и сохранить его в выбранном месте назначения.

Например:

parser.add_option("-f", "--file",
                  action="store", type="string", dest="filename")

Теперь давайте составим поддельную командную строку и попросим, чтобы optparse распарсил её:

args = ["-f", "foo.txt"]
(options, args) = parser.parse_args(args)

Когда optparse видит параметр строки -f, он использует следующий аргумент foo.txt и сохраняет его в options.filename. Так что, после этого вызова parse_args(), options.filename "foo.txt".

Некоторые другие типы опций, поддерживаемые optparse, являются int и float. Вот параметр, который ожидает целочисленный аргумент:

parser.add_option("-n", type="int", dest="num")

Обратите внимание, что эта опция не имеет длинной опции строки, что совершенно приемлемо. Кроме того, нет явного действия, так как по умолчанию установлено значение store.

Давайте разберем еще одну фальшивую командную строку. На этот раз мы заклиним аргумент опции прямо против опции: поскольку -n42 (один аргумент) эквивалентен -n 42 (два аргумента), код:

(options, args) = parser.parse_args(["-n42"])
print(options.num)

будет печатать 42.

Если тип не указан, optparse предполагает string. В сочетании с тем, что действие по умолчанию является store, это означает, что наш первый пример может быть намного короче:

parser.add_option("-f", "--file", dest="filename")

Если адресат не указан, optparse вычисляет разумное значение по умолчанию из опции строки: если первый длинный параметр строка является --foo-bar, то адресатом по умолчанию является foo_bar. Если нет длинной опции строки, optparse смотрит на первую короткую опцию строка: по умолчанию назначение для -f равно f.

optparse также включает в себя встроенный тип complex. Добавление типов описано в разделе Расширение optparse.

Обработка логических опций (флажков)

Флаг опции устанавливает переменную к истинному или ложному, когда особый опции видеть довольно часто. optparse поддерживает их двумя отдельными действиями, store_true и store_false. Например, у вас может быть флаг verbose, который включен с помощью -v и выключен с помощью -q:

parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose")

Здесь у нас есть две различных опции с тем же местом назначения, которое совершенно в порядке. (Это просто означает, что вы должны быть немного осторожными, устанавливая значения по умолчанию — см. ниже.)

Когда optparse сталкивается с -v на командной строке, это устанавливает options.verbose в True; при встрече с -q, options.verbose устанавливается в False.

Другие действия

Некоторые другие действия, поддерживаемые optparse:

"store_const"
сохранить константное значение
"append"
добавить аргумент этого параметра в список
"count"
приращение счетчика на единицу
"callback"
вызвать указанную функцию

Они описаны в разделе Справочное руководство и разделе Колбэки Option.

Значения по умолчанию

Все вышеприведенные примеры включают установку некоторой переменной («назначения»), когда видны определенные параметры командной строки. Что будет, если эти опции никогда не увидят? Так как мы не предоставили никаких значений по умолчанию, они все настроены на 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() OpterParser, который можно вызвать в любое время перед вызовом parse_args():

parser.set_defaults(verbose=True)
parser.add_option(...)
(options, args) = parser.parse_args()

Как и ранее, последняя значение, указанная для данного назначения опции, является той, которая подсчитывает. Для ясности попробуйте использовать один или другой метод установки значения по умолчанию, а не оба.

Создание справки

Способность optparse автоматически генерировать справку и текст использования полезна для создания удобных интерфейсов командной строки. Все, что вам нужно сделать, это предоставить help значение для каждой опции и дополнительно короткое сообщение об использовании для всей программы. Ниже приведен анализ параметров, заполненный удобными для пользователя (документированными) параметрами:

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(), это печатает следующее к стандарту output:

Usage: <yourscript> [options] arg1 arg2

Options:
  -h, --help            show this help message and exit
  -v, --verbose         make lots of noise [default]
  -q, --quiet           be vewwy quiet (I'm hunting wabbits)
  -f FILE, --filename=FILE
                        write output to FILE
  -m MODE, --mode=MODE  interaction mode: novice, intermediate, or
                        expert [default: intermediate]

(Если вывод справки инициируется параметром help, optparse завершает работу после печати текста справки.

Здесь много чего происходит, чтобы помочь optparse создать лучшее из возможных справочных сообщений:

  • сценарий определяет собственное сообщение об использовании:

    usage = "usage: %prog [options] arg1 arg2"
    

    optparse расширяет %prog в строка использования до имени текущей программы, т.е. os.path.basename(sys.argv[0]). Развернутая строка затем печатается перед подробной справкой по опциям.

    Если вы не предоставляете использование строка, optparse использует пустое, но разумное значение по умолчанию: "Usage: %prog [options]", что хорошо, если ваш сценарий не принимает никаких позиционных аргументов.

  • каждая опция определяет строку помощи и не волнуется о обертке-строк, optparse заботится об обертывании линий и том, чтобы заставлять продукцию помощи выглядеть хорошим.

  • параметры, принимающие значение, указывают этот факт в автоматически генерируемом справочном сообщении, например, для параметра «mode»:

    -m MODE, --mode=MODE
    

    Здесь «MODE» вызывается мета-переменной: она расшифровывается как аргумент, который пользователь должен предоставить в -m/--mode. По умолчанию optparse преобразует имя целевой переменной в верхний регистр и использует его для мета-переменной. Иногда это не то, что вы want—for пример, параметр --filename явно задает metavar="FILE", что приводит к этому автоматически генерируемому описанию опции:

    -f FILE, --filename=FILE
    

    Однако это важно не только для экономии места: написанный вручную текст справки использует мета-переменную FILE, чтобы подсказать пользователю, что существует связь между полуформальным синтаксисом -f FILE и неформальным семантическим описанием «запись вывода в FILE». Это простой, но эффективный способ сделать текст справки намного понятнее и полезнее для конечных пользователей.

  • опции, у которых есть значение по умолчанию, могут включать %default в строку — optparse помощи, заменит его str() значение опции по умолчанию. Если у опции нет значения по умолчанию (или значение по умолчанию - None), %default расширяется до none.

Параметры группировки

При работе со многими опциями удобно группировать эти опции для лучшего вывода справки. OptionParser может содержать несколько групп опций, каждая из которых может содержать несколько опций.

Группа опций получается с помощью класса OptionGroup:

class optparse.OptionGroup(parser, title, description=None)

где

  • парсер является OptionParser сущность
  • группа будет вставлена в название - названия группы
  • описание необязательное, является длинным описанием группы

OptionGroup наследует OptionContainer (как OptionParser) и таким образом, метод add_option() может быть используемый, чтобы добавить опцию к группе.

Как только все опции объявлены, используя метод OptionParser add_option_group(), группа добавлена к ранее определенному парсер.

Продолжение работы с парсер, определенными в предыдущем разделе, позволяет легко добавить OptionGroup в парсер:

group = OptionGroup(parser, "Dangerous Options",
                    "Caution: use these options at your own risk.  "
                    "It is believed that some of them bite.")
group.add_option("-g", action="store_true", help="Group option.")
parser.add_option_group(group)

Это приведет к следующим выводам справки:

Usage: <yourscript> [options] arg1 arg2

Options:
  -h, --help            show this help message and exit
  -v, --verbose         make lots of noise [default]
  -q, --quiet           be vewwy quiet (I'm hunting wabbits)
  -f FILE, --filename=FILE
                        write output to FILE
  -m MODE, --mode=MODE  interaction mode: novice, intermediate, or
                        expert [default: intermediate]

  Dangerous Options:
    Caution: use these options at your own risk.  It is believed that some
    of them bite.

    -g                  Group option.

Несколько более полный пример может включать использование нескольких групп: все еще расширение предыдущего примера:

group = OptionGroup(parser, "Dangerous Options",
                    "Caution: use these options at your own risk.  "
                    "It is believed that some of them bite.")
group.add_option("-g", action="store_true", help="Group option.")
parser.add_option_group(group)

group = OptionGroup(parser, "Debug Options")
group.add_option("-d", "--debug", action="store_true",
                 help="Print debug information")
group.add_option("-s", "--sql", action="store_true",
                 help="Print all SQL statements executed")
group.add_option("-e", action="store_true", help="Print every action done")
parser.add_option_group(group)

это приводит к следующим выводам:

Usage: <yourscript> [options] arg1 arg2

Options:
  -h, --help            show this help message and exit
  -v, --verbose         make lots of noise [default]
  -q, --quiet           be vewwy quiet (I'm hunting wabbits)
  -f FILE, --filename=FILE
                        write output to FILE
  -m MODE, --mode=MODE  interaction mode: novice, intermediate, or expert
                        [default: intermediate]

  Dangerous Options:
    Caution: use these options at your own risk.  It is believed that some
    of them bite.

    -g                  Group option.

  Debug Options:
    -d, --debug         Print debug information
    -s, --sql           Print all SQL statements executed
    -e                  Print every action done

Другим интересным методом, в частности, при работе программно с группами опций, является:

OptionParser.get_option_group(opt_str)

Возвращает OptionGroup, к которому относится короткий или длинную строку opt_str (например, '-o' или '--option'). Если такой OptionGroup нет, возвращает None.

Печать строку версии

Аналогично краткому использованию строка, optparse также можете напечатать версию строка для вашей программы. Вы должны поставлять строка как аргумент version OptionParser:

parser = OptionParser(usage="%prog [-f] [-q]", version="%prog 1.0")

%prog расширяется так же, как и в usage. Кроме того, version может содержать все, что угодно. При его поставке optparse автоматически добавляет в парсер опцию --version. Если этот параметр появляется в командной строке, он расширяет ваш version строка (заменяя %prog), печатает его до stdout и выходит.

Например, если сценарий вызывается /usr/bin/foo:

$ /usr/bin/foo --version
foo 1.0

Следующие два метода могут быть используемый, чтобы напечатать и получить version строка:

OptionParser.print_version(file=None)

Печать сообщения о версии для текущей программы (self.version) на file (по умолчанию stdout). Как и в случае с print_usage(), любое вхождение %prog в self.version заменяется именем текущей программы. Ничего не делает, если self.version пуст или не определен.

OptionParser.get_version()

То же как print_version(), но возвращает версия строка вместо того, чтобы печатать его.

Как optparse обрабатывает ошибки

Есть два широких класса ошибок, о которых optparse должен беспокоиться: ошибки программистов и ошибки пользователей. Ошибки программиста обычно являются ошибочными вызовами OptionParser.add_option(), например, недопустимая опция строки, неизвестная опция атрибуты, отсутствующая опция атрибуты и т.д. С ними разбираются обычным образом: вызывают исключение (либо optparse.OptionError, либо TypeError) и дают программе потерпеть крах.

Обработка пользовательских ошибок гораздо важнее, так как они гарантированно происходят независимо от того, насколько стабильна ваша код. optparse может автоматически обнаруживать некоторые ошибки пользователя, такие как неправильные аргументы параметра (передача -n 4x где -n принимает целочисленный аргумент), отсутствующие аргументы (-n в конце командной строки, где -n принимает аргумент любого типа). Кроме того, можно вызвать функцию OptionParser.error() для сигнализации состояния ошибки, определяемого приложением:

(options, args) = parser.parse_args()
...
if options.a and options.b:
    parser.error("options -a and -b are mutually exclusive")

В любом случае, optparse обрабатывает ошибку так же: он печатает сообщение об использовании программы и сообщение об ошибке для стандартной ошибки и выходит со статусом ошибки 2.

Рассмотрите первый пример выше, куда пользователь передает 4x к опции, который получает интеджер:

$ /usr/bin/foo -n 4x
Usage: foo [options]

foo: error: option -n: invalid integer value: '4x'

Или, если пользователь вообще не может передать значение:

$ /usr/bin/foo -n
Usage: foo [options]

foo: error: -n option requires an argument

В сообщениях об ошибках optparse всегда упоминается опция, связанная с ошибкой; не забудьте сделать то же самое при вызове OptionParser.error() из приложения код.

Если поведение обработки ошибок optparse по умолчанию не удовлетворит вашим потребностям, то вы будете нуждаться к подкласс OptionParser и отвергать его exit() и/или методы error().

Все вместе

Вот как обычно выглядят сценарии на основе optparse:

from optparse import OptionParser
...
def main():
    usage = "usage: %prog [options] arg"
    parser = OptionParser(usage)
    parser.add_option("-f", "--file", dest="filename",
                      help="read data from FILENAME")
    parser.add_option("-v", "--verbose",
                      action="store_true", dest="verbose")
    parser.add_option("-q", "--quiet",
                      action="store_false", dest="verbose")
    ...
    (options, args) = parser.parse_args()
    if len(args) != 1:
        parser.error("incorrect number of arguments")
    if options.verbose:
        print("reading %s..." % options.filename)
    ...

if __name__ == "__main__":
    main()

Справочное руководство

Создание парсера

Первый шаг в использовании optparse - создание сущности OpterParser.

class optparse.OptionParser(...)

У конструктора OptionParser нет необходимых аргументов, но многих дополнительных аргументов ключевой. Вы всегда должны передавать их как ключевой аргументы, т.е. не полагаться на порядок, в котором аргументы объявлены.

usage (по умолчанию: "%prog [options]")
сводка по использованию для печати, когда программа запущена неправильно или с параметром справки. Когда optparse печатает использование строка, это расширяет %prog до os.path.basename(sys.argv[0]) (или до prog, если вы передали этому аргумент ключевой). Чтобы подавить сообщение использования, передать специальный значение optparse.SUPPRESS_USAGE.
option_list (по умолчанию: [])
список Option объектов, чтобы заполнить парсер. Параметры в option_list добавляются после любых параметров в standard_option_list (класс атрибут, который может быть задан OpterParser подклассы), но перед любой версией или параметрами справки. Осуждаемый; используйте add_option() после создания парсер.
option_class (по умолчанию: optparse.Option)
Класс, используемый при добавлении опций к парсер в add_option().
version (по умолчанию: None)
Версия строка для печати, когда пользователь предоставляет параметр версии. При вводе истинной значение для version optparse автоматически добавляет опцию версии с единственной опцией строка --version. Подстрока %prog расширяется так же, как и для usage.
conflict_handler (по умолчанию: "error")
определяет, что сделать, когда опции с противоречивой опцией строки добавлены к парсер; см. раздел Конфликты между опциями.
description (по умолчанию: None)
абзац текста, дающий краткий обзор программы. optparse переформатирует этот абзац в соответствии с текущей шириной терминала и печатает его, когда пользователь запрашивает справку (после usage, но перед списком опций).
formatter (по умолчанию: новый IndentedHelpFormatter)
сущность optparse. HelpFormatter, который будет использоваться для печати текста помощи. Для этой цели optparse предоставляет два конкретных класса: IndicedHelpFormatter и TitledHelpFormatter.
add_help_option (по умолчанию: True)
Если true, optparse добавит опцию помощи (с строкой опции -h и --help) к парсеру.
prog
строка для использования при развертывании %prog в usage и version вместо os.path.basename(sys.argv[0]).
epilog (по умолчанию: None)
абзац текста справки для печати после опции help.

Заполнение парсера

Существует несколько способов заполнения парсер опциями. Предпочтительный путь при помощи OptionParser.add_option(), как показано в разделе Учебник. add_option() можно вызвать одним из двух способов:

  • передать ему Option сущность (как возвращенный make_option())
  • передать ему любую комбинацию позиционных и аргументов ключевой, которые приемлемы для make_option() (т.е. конструктору Option), и это создаст Option сущность для вас

Другая альтернатива должна передать список предварительно построенного Option сущности конструктору OptionParser, как в:

option_list = [
    make_option("-f", "--filename",
                action="store", type="string", dest="filename"),
    make_option("-q", "--quiet",
                action="store_false", dest="verbose"),
    ]
parser = OptionParser(option_list=option_list)

(make_option() - заводская функция для создания Option сущности; в настоящее время является алиас для конструктора Option. Будущая версия optparse может разделить Option на несколько классов, и make_option() выберет нужный класс для создания экземпляра. Не создавайте экземпляр Option напрямую.)

Определение опций

Каждая Option сущность представляет набор синонимичных опций командной строки строки, например -f и --file. Можно указать любое количество коротких или длинных опций строки, но необходимо указать по крайней мере один общий параметр строка.

Канонический способ создания Option сущность - с add_option() методом OptionParser.

OptionParser.add_option(option)
OptionParser.add_option(*opt_str, attr=value, ...)

Определение опции только с короткой опцией строка:

parser.add_option("-f", attr=value, ...)

И определить опцию только с длинной опцией строка:

parser.add_option("--foo", attr=value, ...)

Аргументы ключевой определяют атрибуты нового объекта Option. Самый важный атрибут опции - action и это в основном, определяет, который другие атрибуты релевантны или необходимы. Если вы передаете неактуальную опцию атрибутов или не передаете требуемые, optparse вызывает исключение OptionError, объясняющее вашу ошибку.

Параметр action определяет, что делает optparse при обнаружении этого параметра в командной строке. Стандартные действия опций, жестко закодированные в optparse:

"store"
сохранить аргумент этого параметра (по умолчанию)
"store_const"
хранить постоянную значение
"store_true"
хранить True
"store_false"
хранить False
"append"
добавить аргумент этого параметра в список
"append_const"
добавить константу значение в список
"count"
приращение счетчика на единицу
"callback"
вызвать указанную функцию
"help"
распечатайте сообщение об использовании, включая все опции и документацию для них

(Если действие не задано, значение по умолчанию равно "store". Для этого действия можно также предоставить опции type и dest атрибуты; см. Стандартные действия опций.)

Как видно, большинство действий включает в себя хранение или обновление значение где-либо. optparse всегда создает для этого специальный объект, традиционно вызываемый options (это бывает сущность optparse.Values). Аргументы опции (и различный другой значения) сохранены как атрибуты этого объекта, согласно dest (место назначения) атрибут опции.

Например, при вызове:

parser.parse_args()

одна из первых вещей, которые делает optparse, создают объект options:

options = Values()

Если одна из опций в этой парсер определена как:

parser.add_option("-f", "--file", action="store", type="string", dest="filename")

и анализируемая командная строка включает в себя любую из следующих команд:

-ffoo
-f foo
--file=foo
--file foo

тогда optparse, увидев эту опцию, сделает эквивалент:

options.filename = "foo"

type и dest, атрибуты опции почти так же важны как action, но action - единственный, который имеет смысл для всех опций.

Атрибуты Option

Следующий параметр атрибуты может быть передан в качестве аргументов ключевой 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.

Option.callback_args
Option.callback_kwargs

Дополнительные позиционные и ключевой аргументы для передачи в callback после четырех стандартных колбэк аргументов.

Option.help

Текст справки для печати при перечислении всех доступных опций после предоставления пользователем опции help (например, --help). Если текст справки не указан, параметр будет указан без текста справки. Чтобы скрыть этот параметр, используйте специальный параметр значение optparse.SUPPRESS_HELP.

Option.metavar

(по умолчанию - производное от опции строки)

Замена для опции аргументов, используемых при печати текста справки. Пример см. в разделе Учебник.

Стандартные действия опций

Различные действия опций имеют несколько разные требования и эффекты. У большинства действий есть несколько соответствующих атрибутов опций, который вы можете определить, чтобы вести поведение optparse; для некоторых из них требуются атрибуты, которые необходимо указать для любой опции, использующей это действие.

  • "store" [релевантно: type, dest, nargs, choices]

    За параметром должен следовать аргумент, который преобразуется в значение в соответствии с type и сохраняется в dest. Если nargs > 1, из командной строки будет использовано несколько аргументов; все будут преобразованы согласно type и сохранены к dest как кортеж. См. раздел Стандартные типы опций.

    Если choices поставляется (список или кортеж строки), по умолчаниюы типа к "choice".

    Если параметр type не указан, по умолчанию устанавливается значение "string".

    Если dest не поставляется, optparse получает место назначения из первой длинной строки опции (например, --foo-bar подразумевает foo_bar). Если не существует длинной опции строки, optparse выводит адресат из первой короткой опции строка (например, -f подразумевает f).

    Пример:

    parser.add_option("-f")
    parser.add_option("-p", type="float", nargs=3, dest="point")
    

    По мере разбора командной строки:

    -f foo.txt -p 1 -3.5 4 -fbar.txt
    

    optparse установит:

    options.f = "foo.txt"
    options.point = (1.0, -3.5, 4.0)
    options.f = "bar.txt"
    
  • "store_const" [обязательно: const; соответствующее: dest]

    Значение const хранится в dest.

    Пример:

    parser.add_option("-q", "--quiet",
                      action="store_const", const=0, dest="verbose")
    parser.add_option("-v", "--verbose",
                      action="store_const", const=1, dest="verbose")
    parser.add_option("--noisy",
                      action="store_const", const=2, dest="verbose")
    

    Если --noisy увидят, optparse установит:

    options.verbose = 2
    
  • "store_true" [релевантно: dest] особый случай "store_const", в котором хранятся True dest.

  • "store_false" [релевантно: dest]

    Как "store_true", но хранит False.

    Пример:

    parser.add_option("--clobber", action="store_true", dest="clobber")
    parser.add_option("--no-clobber", action="store_false", dest="clobber")
    
  • "append" [релевантно: type, dest, nargs, choices]

    За опцией должен следовать аргумент, который добавляется к списку в dest. Если не значения по умолчанию для dest поставляется, пустой список, автоматически не создан, когда optparse сначала сталкивается с этой опцией в командной строке. Если nargs > 1, используется несколько аргументов, и кортеж длины 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)
    

    Более подробную информацию см. в разделе Колбэки Option.

  • "help"

    Печать полного справочного сообщения для всех параметров текущей опции парсер. Справочное сообщение создается из usage строка, переданного конструктору OpterParser, и help строка передается каждому параметру.

    Если не help строка будет поставляться для опции, то он будет все еще перечислен в сообщении помощи. Чтобы полностью опустить опцию, используйте специальный значение optparse.SUPPRESS_HELP.

    optparse автоматически добавляет параметр help ко всем параметрическим парсерам, поэтому обычно его создавать не требуется.

    Пример:

    from optparse import OptionParser, SUPPRESS_HELP
    
    # usually, a help option is added automatically, but that can
    # be suppressed using the add_help_option argument
    parser = OptionParser(add_help_option=False)
    
    parser.add_option("-h", "--help", action="help")
    parser.add_option("-v", action="store_true", dest="verbose",
                      help="Be moderately verbose")
    parser.add_option("--file", dest="filename",
                      help="Input file to read data from")
    parser.add_option("--secret", help=SUPPRESS_HELP)
    

    Если optparse будет видеть или -h или --help на командной строке, то это напечатает что-то как следующее сообщение помощи к stdout (предполагающий, что sys.argv[0] - "foo.py"):

    Использование: foo.py [параметры]
    
    Параметры: -h, --help показать это справочное сообщение и выйти из -v быть
    умеренно подробным --file = FILENAME входной файл для чтения данных из
    

    После печати справочного сообщения optparse завершает процесс с помощью sys.exit(0).

  • "version"

    Печатает номер версии, предоставленный анализатору параметров для stdout и выхода. Номер версии на самом деле отформатирован и напечатан методом print_version() OptionParser. Обычно только релевантный, если аргумент version поставляется конструктору OptionParser. Как с опцией help, вы будете редко создавать опции version, так как optparse автоматически добавляет их при необходимости.

Стандартные типы опций

optparse имеет пять встроенных типов опций: "string", "int", "choice", "float" и "complex". Если необходимо добавить новые типы опций, см. раздел Расширение optparse.

Аргументы в параметры строка не проверяются и не преобразуются каким-либо образом: текст в командной строке хранится в месте назначения (или передается в колбэк) как есть.

Целочисленные аргументы (тип "int") анализируются следующим образом:

  • если число начинается с 0x, оно анализируется как шестнадцатеричное число
  • если число начинается с 0, оно анализируется как восьмеричное число
  • если число начинается с 0b, оно анализируется как двоичное число
  • в противном случае число анализируется как десятичное число

Преобразование выполняется путем вызова int() с соответствующей базой (2, 8, 10 или 16). Если это не удается, то optparse, хотя и с более полезным сообщением об ошибке.

Аргументы опций "float" и "complex" преобразуются непосредственно с помощью float() и complex() с аналогичной обработкой ошибок.

Параметры "choice" являются подтипом параметров "string". Параметр choices атрибут (последовательность строки) определяет набор допустимых аргументов параметра. optparse.check_choice() сравнивает снабженные пользователями аргументы опции с этим основным списком и поднимает OptionValueError, если передана недействительная строка.

Парсинг аргументов

Весь смысл создания и заполнения OpterParser заключается в вызове метода parse_args():

(options, args) = parser.parse_args(args=None, values=None)

где находятся входные параметры

args
список аргументов для обработки (по умолчанию sys.argv[1:])
values
объект optparse.Values для хранения аргументов опции в (по умолчанию: новая сущность Values) - если задать существующий объект, параметры опции по умолчанию на нем инициализироваться не будут

и возвращает значения являются

options
тот же объект, который был передан как values, или optparse. Значения сущность созданы optparse
args
оставшиеся позиционные аргументы после обработки всех опций

Наиболее часто используется для указания ни одного из аргументов ключевой. Если вы предоставляете values, он будет изменен с повторными вызовами setattr() (примерно по одному для каждого аргумента опции, сохраненного в адресате опции) и возвращенный по parse_args().

Если parse_args() сталкивается с какими-либо ошибками в списке аргументов, он вызывает метод OptionParser error() с соответствующим сообщением об ошибке конечного пользователя. Это в конечном итоге завершает процесс со статусом выхода 2 (традиционный статус выхода Unix для ошибок командной строки).

Запрос и манипулирование опциеями парсер

Поведение опции парсер по умолчанию можно настроить незначительно, и вы также можете обойти вашу опцию парсер и увидеть, что там. Opрамках Parser предоставляет несколько методов, которые помогают:

OptionParser.disable_interspersed_args()

Установите для параметра парсинг значение stop на первом невыпадающем параметре. Например, если -a и -b - оба простые опции, которые не принимают аргументов, optparse обычно принимает этот синтаксис:

prog -a arg1 -b arg2

и рассматривает это как эквивалентное:

prog -a -b arg1 arg2

Для отключения этой функции вызвать функцию disable_interspersed_args(). Это восстанавливает традиционный синтаксис Unix, где параметр парсинг останавливается с первым аргументом, не являющимся параметром.

Используйте это, если у вас есть процессор команд, который запускает другую команду, которая имеет собственные параметры, и вы хотите убедиться, что эти параметры не путаются. Например, каждая команда может иметь различный набор параметров.

OptionParser.enable_interspersed_args()

Установите для параметра «» парсинг «» значение «» не останавливаться «» на первом невыпадающем параметре, разрешив перемежающиеся ключи с аргументами команды. Это поведение по умолчанию.

OptionParser.get_option(opt_str)

Возвращает Option сущность с строкой opt_str опцией или None, если ни у каких опций нет строки опции.

OptionParser.has_option(opt_str)

Возвращает True, если у OptionParser есть опция с строкой opt_str опции (например, -q или --verbose).

OptionParser.remove_option(opt_str)

Если OptionParser имеет опцию, соответствующую opt_str, эта опция удаляется. Если тот опцию предоставил какую-либо другую опцию строки, все те опции, строки становятся недействительными. Если opt_str не возникает ни в одной из опций, принадлежащих этому OptionParser, поднимает ValueError.

Конфликты между опциями

Если вы не осторожны, легко определить параметры с конфликтующими параметрами строки:

parser.add_option("-n", "--dry-run", ...)
...
parser.add_option("-n", "--noisy", ...)

(Это особенно верно, если вы определили свой собственный OptionParser подкласс с некоторыми стандартными опциями.)

Каждый раз при добавлении опции optparse проверяет наличие конфликтов с существующими опциями. При обнаружении он вызывает текущий механизм обработки конфликтов. Механизм обработки конфликтов можно задать в конструкторе:

parser = OptionParser(..., conflict_handler=handler)

или с отдельным вызовом:

parser.set_conflict_handler(handler)

Доступные обработчики конфликтов:

"error" (по умолчанию)
предполагают, что конфликты опции - программная ошибка и поднимают OptionConflictError
"resolve"
интеллектуальное разрешение конфликтов опций (см. ниже)

Как пример, давайте определим OptionParser, который решает конфликты разумно, и добавьте противоречивые опции к нему:

parser = OptionParser(conflict_handler="resolve")
parser.add_option("-n", "--dry-run", ..., help="do no harm")
parser.add_option("-n", "--noisy", ..., help="be noisy")

В этот момент параметр optparse обнаруживает, что ранее добавленный параметр уже использует параметр -n строка. Поскольку conflict_handler является "resolve", он разрешает ситуацию, удаляя -n из списка опций строки, ранее использовавшихся в опционе. Теперь --dry-run - это единственный способ для пользователя активировать эту опцию. Если пользователь запросит помощь, это будет отражено в справке:

Options:
  --dry-run     do no harm
  ...
  -n, --noisy   be noisy

Можно отбросить опцию строки для ранее добавленной опции до тех пор, пока ее не останется, и пользователь не сможет вызвать ее из командной строки. В этом случае optparse полностью удаляет этот параметр, поэтому он не отображается в тексте справки или где-либо еще. Продолжение работы с существующим анализатором параметров:

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’s, но вы можете хотеть сломать циклические ссылки явно, вызывая destroy() на вашем OptionParser, как только вы сделаны с ним. Это особенно полезно в длительных приложениях, где к графам больших объектов можно получить доступ с помощью OpterParser.

Другие методы

Opрамках Parser поддерживает несколько других публичных методов:

OptionParser.set_usage(usage)

Установите использование строка согласно правилам, описанным выше для конструктора usage аргумент ключевой. Передача None задает использование по умолчанию строка; используйте optparse.SUPPRESS_USAGE для подавления сообщения об использовании.

OptionParser.print_usage(file=None)

Распечатайте сообщение об использовании для текущей программы (self.usage) на file (stdout по умолчанию). Любое вхождение строка %prog в self.usage заменяется именем текущей программы. Ничего не делает, если self.usage пуст или не определен.

OptionParser.get_usage()

То же как print_usage(), но возвращает использование строка вместо того, чтобы печатать его.

OptionParser.set_defaults(dest=value, ...)

Установите значения по умолчанию для нескольких опций назначения одновременно. Использование set_defaults() является предпочтительным способом установки значения по умолчанию для опций, так как несколько опций могут совместно использовать одно и то же назначение. Например, если несколько опций «mode» задают один и тот же адресат, любой из них может установить значение по умолчанию, а последний выигрывает:

parser.add_option("--advanced", action="store_const",
                  dest="mode", const="advanced",
                  default="novice")    # overridden below
parser.add_option("--novice", action="store_const",
                  dest="mode", const="novice",
                  default="advanced")  # overrides above setting

Чтобы избежать этой путаницы, используйте set_defaults():

parser.set_defaults(mode="advanced")
parser.add_option("--advanced", action="store_const",
                  dest="mode", const="advanced")
parser.add_option("--novice", action="store_const",
                  dest="mode", const="novice")

Колбэки Option

Когда встроенные действия и типы optparse не достаточно для ваших потребностей, у вас есть два выбора: расширьте optparse или определите колбэк опции. Расширение optparse является более общим, но чрезмерным для многих простых случаев. Довольно часто простой колбэк - это все, что вам нужно.

Есть два шага, чтобы определить колбэк опции:

  • определить саму опцию, используя "callback" действие
  • написать колбэк; это функция (или метод), которая принимает по крайней мере четыре аргумента, как описано ниже

Определение колбэков опций

Как всегда, самый простой способ определения опции колбэка - это использование метода OptionParser.add_option(). Кроме action, единственная опция атрибута, который вы должны определить, является callback, функция вызова:

parser.add_option("-c", action="callback", callback=my_callback)

callback является функцией (или другим вызываемым объектом), поэтому при создании этой опции колбэк необходимо определить my_callback(). В этом простом случае даже не знает optparse, берет ли -c какие-либо аргументы, который обычно означает, что опция принимает не аргументы — простое присутствие -c на командной строке - все, что это должно знать. Однако в некоторых случаях может потребоваться, чтобы ваши колбэк потребляли произвольное количество аргументов командной строки. Вот где писать колбэки становится непросто; он рассматривается ниже в этом разделе.

optparse всегда передает четыре конкретных аргумента вашему колбэк, и он будет передавать дополнительные аргументы, только если вы указываете их через callback_args и callback_kwargs. Таким образом минимальная сигнатура функции колбэка:

def my_callback(option, opt, value, parser):

Четыре аргумента колбэк описаны ниже.

Существует несколько других опций атрибуты, которые можно предоставить при определении опции колбэк:

type
имеет свое обычное значение: как и в случае "store" или "append" действий, он предписывает optparse использовать один аргумент и преобразовать его в type. Вместо того, чтобы хранить преобразованные значение где-либо, optparse передает их функции колбэк.
nargs
также имеет своё обычное значение: если он поставляется и > 1, optparse будет потреблять nargs аргументы, каждый из которых должен быть конвертируемым в type. Затем он передает кортеж преобразованных значения вашему колбэк.
callback_args
кортеж дополнительных позиционных аргументов для передачи колбэк
callback_kwargs
словарь дополнительных аргументов ключевой, чтобы пройти к колбэк

Как вызываются колбэки

Все колбэки вызываются следующим образом:

func(option, opt_str, value, parser, *args, **kwargs)

где

option
Option сущность, который вызывает колбэк
opt_str
параметр строка, отображаемый в командной строке, которая запускает колбэк. (Если использовалась сокращенная длинная опции, opt_str будет полным, канонической строкой опции — т.е. если пользователь помещает --foo в командной строке в качестве аббревиатуры для --foobar, то opt_str будет "--foobar".)
value
аргумент для этого параметра, отображаемый в командной строке. optparse будет только ожидать аргумент, если type будет установлен; тип value будет типом, подразумеваемым типом опции. Если значение type для этого параметра равно None (аргумент не ожидается), то значение value будет равно None. Если nargs > 1, value будет кортежем значения соответствующего типа.
parser

является сущностью OptionParser управляя всем, в основном полезно, потому что вы можете получить доступ к некоторым другим интересным данным через его сущность атрибуты:

parser.largs
текущий список оставшихся аргументов, т. е. аргументы, которые были использованы, но не являются ни опциями, ни аргументами опционов. Не стесняйтесь изменять parser.largs, например, добавляя в него дополнительные аргументы. (Этот список станет args, вторым возвращает значение parse_args().
parser.rargs
текущий список оставшихся аргументов, т. е. с opt_str и value (если применимо) удалены, и только аргументы, следующие за ними все еще там. Не стесняйтесь изменять parser.rargs, например, потребляя больше аргументов.
parser.values
объект, в котором по умолчанию хранятся опции значения (сущность optparse. OptionValues). Это позволяет колбэки использовать тот же механизм в качестве остальной части optparse для хранения значения опции; вам не нужно связываться с глобалами или закрытиями. Вы можете также получить доступ или изменить значение(ий) любых опций, с которыми уже сталкиваются на командной строке.
args
представляет собой кортеж произвольных позиционных аргументов, поставляемых через опцию callback_args атрибут.
kwargs
словарь произвольных аргументов ключевой, поставляемый через callback_kwargs.

Поднятие ошибок в колбэке

Функция колбэк должна вызывать OptionValueError при возникновении проблем с опцией или ее аргументами. optparse ловит это и завершает программу, распечатывая сообщение об ошибке, которое вы передаете stderr. Ваше сообщение должно быть четким, лаконичным, точным и упоминать опцию по ошибке. В противном случае пользователю будет трудно понять, что они сделали неправильно.

Колбэк пример 1: тривиальный колбэк

Вот пример опции колбэка, который не принимает аргументов и просто записывает, что параметр был замечен:

def record_foo_seen(option, opt_str, value, parser):
    parser.values.saw_foo = True

parser.add_option("--foo", action="callback", callback=record_foo_seen)

Конечно, вы можете сделать это с помощью действия "store_true".

Колбэк пример 2: проверить порядок опций

Вот несколько более интересный пример: зафиксируйте тот факт, что -a виден, но взорвется, если он наступит после -b в командной строке.:

def check_order(option, opt_str, value, parser):
    if parser.values.b:
        raise OptionValueError("can't use -a after -b")
    parser.values.a = 1
...
parser.add_option("-a", action="callback", callback=check_order)
parser.add_option("-b", action="store_true", dest="b")

Колбэк пример 3: порядок опций проверки (обобщенный)

Если вы хотите повторно использовать это колбэк для нескольких аналогичных опций (установить флаг, но взорвать, если -b уже был замечен), это требует немного работы: сообщение об ошибке и флаг, который он устанавливает, должны быть обобщены:

def check_order(option, opt_str, value, parser):
    if parser.values.b:
        raise OptionValueError("can't use %s after -b" % opt_str)
    setattr(parser.values, option.dest, 1)
...
parser.add_option("-a", action="callback", callback=check_order, dest='a')
parser.add_option("-b", action="store_true", dest="b")
parser.add_option("-c", action="callback", callback=check_order, dest='c')

Колбэк пример 4: проверить произвольное условие

Конечно, вы можете поставить любое условие в этом —вы не ограничиваетесь проверкой значения уже определенных опций. Например, если у вас есть опции, которые не следует вызывать, когда полнолуние, все, что вам нужно сделать, это это:

def check_moon(option, opt_str, value, parser):
    if is_moon_full():
        raise OptionValueError("%s option invalid when moon is full"
                               % opt_str)
    setattr(parser.values, option.dest, 1)
...
parser.add_option("--foo",
                  action="callback", callback=check_moon, dest="foo")

(Определение is_moon_full() оставлено в качестве упражнения для читателя.

Колбэк пример 5: фиксированные аргументы

Вещи становятся немного интереснее, когда вы определяете параметры колбэк, которые принимают фиксированное количество аргументов. Указание того, что параметр колбэк принимает аргументы, аналогично определению параметра "store" или "append": если определить type, то параметр принимает один аргумент, который должен быть преобразован в этот тип; если дополнительно определить nargs, то опция принимает аргументы nargs.

Вот пример, который просто эмулирует стандартное действие "store":

def store_value(option, opt_str, value, parser):
    setattr(parser.values, option.dest, value)
...
parser.add_option("--foo",
                  action="callback", callback=store_value,
                  type="int", nargs=3, dest="foo")

Обратите внимание, что optparse заботится о потреблении 3 аргументов и преобразование их в целые числа для вас; все, что вам нужно сделать, это хранить их. (Или что угодно; очевидно, что вам не нужен колбэк для этого примера.)

Колбэк пример 6: переменные аргументы

Вещи становятся волосатыми, когда вы хотите, чтобы параметр принял переменное количество аргументов. Для этого случая необходимо написать колбэк, так как optparse не предоставляет для него никаких встроенных возможностей. И вы должны иметь дело с определенной запутанностью обычной командной строки Unix парсинг, с которым optparse обычно обращается для вас. В частности, колбэки должны реализовывать условные правила для голых -- и - аргументов:

  • -- или - могут быть аргументами параметра
  • голый -- (если не аргумент для некоторого параметра): остановить обработку командной строки и отменить --
  • голый - (если не аргумент к какой-то опции): остановить обработку командной строки, но сохранить - (добавить его к parser.largs)

Если ва нужна опция, который принимает переменное количество аргументов, есть несколько тонких, сложных проблем, о которых нужно беспокоиться. Точная реализация, которую вы выберете, будет основана на тех компромиссах, которые вы готовы сделать для вашего приложения (именно поэтому optparse не поддерживает этот вид вещей напрямую).

Тем не менее, вот удар в колбэк для опции с переменными аргументами:

def vararg_callback(option, opt_str, value, parser):
    assert value is None
    value = []

    def floatable(str):
        try:
            float(str)
            return True
        except ValueError:
            return False

    for arg in parser.rargs:
        # остановиться на --foo как опции
        if arg[:2] == "--" and len(arg) > 2:
            break
        # остановитеся на -a, но не на -3 или -3.0
        if arg[:1] == "-" and len(arg) > 1 and not floatable(arg):
            break
        value.append(arg)

    del parser.rargs[:len(value)]
    setattr(parser.values, option.dest, value)

...
parser.add_option("-c", "--callback", dest="vararg_attr",
                  action="callback", callback=vararg_callback)

Расширение optparse

Так как двумя главными факторами управления в том, как optparse интерпретирует параметры командной строки, является действие и тип каждой опций, наиболее вероятное направление расширения должно добавить новые действия и новые типы.

Добавление новых типов

Чтобы добавить новые типы, вы должны определить свой собственный подкласс класса optparse Option. У этого класса есть пара атрибуты, определяющих типы optparse: TYPES и TYPE_CHECKER.

Option.TYPES

Кортеж названий типов; в вашем подкласс просто определите новый кортеж TYPES, который строится на стандартном.

Option.TYPE_CHECKER

Словарь, сопоставляющий имена типов функциям проверки типа. Функция проверки типа имеет следующие сигнатура:

def check_mytype(option, opt, value)

где option - Option сущность, opt - опция строка (например, -f), а value - строка из командной строки, которая должна быть проверена и преобразована в требуемый тип. check_mytype() должен возвращает объект гипотетического типа mytype. значение возвращенный проверяющей тип функцией закончится в OptionValues сущность возвращенный OptionParser.parse_args() или будет передан к колбэк как параметр value.

Ваша проверяющая тип функция должна поднять OptionValueError, если это сталкивается с какими-либо проблемами. OptionValueError берет единственный аргумент строка, который передан как есть к методу OptionParser error(), который в свою очередь предварительно ожидает название программы и строка "error:" и печатает все к stderr прежде, чем закончить процесс.

Вот глупый пример, который демонстрирует добавление типа опции "complex", чтобы разобрать комплексные числа Python-стиля на командной строке. (Это даже полнее, чем используемый быть, потому что optparse 1.3 добавил встроенную поддержку комплексных чисел, но неважно.)

Во-первых, необходимый импорт:

from copy import copy
from optparse import Option, OptionValueError

Сначала необходимо определить средство проверки типа, поскольку оно упоминается позже (в классе TYPE_CHECKER атрибут Option подкласс):

def check_complex(option, opt, value):
    try:
        return complex(value)
    except ValueError:
        raise OptionValueError(
            "option %s: invalid complex value: %r" % (opt, value))

Итоговый Option подкласс:

class MyOption (Option):
    TYPES = Option.TYPES + ("complex",)
    TYPE_CHECKER = copy(Option.TYPE_CHECKER)
    TYPE_CHECKER["complex"] = check_complex

(Если бы мы не сделали copy() Option.TYPE_CHECKER, то мы закончили бы тем, что изменили TYPE_CHECKER атрибут класса Option optparse. Это быть Python, ничто не мешает вам делать это, кроме хороших манер и здравого смысла.)

Именно! теперь вы можете написать сценарий, в котором используется новый тип параметра, как и в любом другом сценарии на основе optparse, за исключением того, что вы должны дать инструкции по использованию MyOption вместо Option:

parser = OptionParser(option_class=MyOption)
parser.add_option("-c", type="complex")

В качестве альтернативы можно создать собственный список опций и передать его в OpterParser; если вы не используете add_option() таким образом, как описано выше, вам не нужно указывать OpterParser, какой класс опций использовать:

option_list = [MyOption("-c", action="store", type="complex", dest="c")]
parser = OptionParser(option_list=option_list)

Добавление новых действий

Добавить новые действия немного сложнее, потому что надо понимать, что у optparse есть пара классификаций для действий:

«сохраняющие» действия
действий, которые приводят к optparse, хранящему значение к атрибут текущего OptionValues сущность; эти опции требуют, чтобы dest атрибут поставлялся конструктору Option.
«типизированные» действия
которые принимают значение из командной строки и ожидают, что он будет определенного типа; или, скорее, строка, который может быть преобразован в определенный тип. Эти опции требуют type атрибут конструктора Option.

Это перекрывающиеся наборы: некоторые действия хранения по умолчанию - "store", "store_const", "append" и "count", в то время как «типизированные» действия по умолчанию - "store", "append" и "callback".

При добавлении действия необходимо классифицировать его по крайней мере в одном из следующих классов атрибутов Option (все являются списками строк):

Option.ACTIONS

Все действия должны быть перечислены в ACTIONS.

Option.STORE_ACTIONS

Здесь дополнительно перечислены действия «store».

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() позаботится о том, чтобы получить его правильно, когда это необходимо.