Spec-Zone.ru › Python 3.13

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

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

Выбор библиотеки для разбора аргументов

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

  • getopt: модуль, практически повторяющий процедурный API языка C getopt. Входит в стандартную библиотеку ещё до первого выпуска Python 1.0.
  • optparse: декларативная замена getopt, предоставляющая аналогичные возможности без необходимости реализовывать в каждом приложении собственную логику процедурного разбора параметров. Входит в стандартную библиотеку начиная с выпуска Python 2.3.
  • argparse: более строгая альтернатива optparse, предоставляющая больше возможностей по умолчанию, но уменьшающая гибкость приложения в управлении точным способом обработки аргументов. Входит в стандартную библиотеку начиная с выпусков Python 2.7 и Python 3.2.

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

getopt сохранён почти исключительно ради обратной совместимости. Однако он также подходит для узкого случая использования: прототипирования и тестирования обработки аргументов командной строки в приложениях на C, основанных на getopt.

optparse стоит рассмотреть в качестве альтернативы argparse в следующих случаях:

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

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

В качестве конкретного примера рассмотрим две следующие конфигурации разбора аргументов командной строки: первая использует optparse, а вторая — argparse:

import optparse

if __name__ == '__main__':
    parser = optparse.OptionParser()
    parser.add_option('-o', '--output')
    parser.add_option('-v', dest='verbose', action='store_true')
    opts, args = parser.parse_args()
    process(args, output=opts.output, verbose=opts.verbose)
import argparse

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-o', '--output')
    parser.add_argument('-v', dest='verbose', action='store_true')
    parser.add_argument('rest', nargs='*')
    args = parser.parse_args()
    process(args.rest, output=args.output, verbose=args.verbose)

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

Однако вариант с argparse также будет иначе обрабатывать некоторые сочетания параметров, чем вариант с optparse. Например (среди прочих различий):

  • при передаче -o -v с optparse будут получены output="-v" и verbose=False, а с argparse возникнет ошибка использования (с сообщением об отсутствии значения для -o/--output, поскольку -v интерпретируется как флаг подробного вывода)
  • аналогично, при передаче -o -- с optparse будут получены output="--" и args=(), а с argparse возникнет ошибка использования (также с сообщением об отсутствии значения для -o/--output, поскольку -- интерпретируется как завершение обработки параметров и перевод всех оставшихся значений в позиционные аргументы)
  • при передаче -o=foo с optparse будет получено output="=foo", а с argparse — output="foo" (поскольку = специально обрабатывается как альтернативный разделитель значений параметров)

Считать ли такое различие в поведении варианта с argparse желательным или проблемным, зависит от конкретного сценария использования приложения командной строки.

См. также

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

Другие сторонние библиотеки, такие как typer или msgspec-click, позволяют задавать интерфейсы командной строки способами, которые лучше интегрируются со статической проверкой аннотаций типов Python.

Введение

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 был специально разработан для поощрения создания программ с простыми интерфейсами командной строки, соответствующими соглашениям, установленным семейством функций getopt(), доступных разработчикам на C. Поэтому он поддерживает только наиболее распространённые синтаксис и семантику командной строки, традиционно используемые в Unix. Если вы не знакомы с этими соглашениями, этот раздел поможет вам с ними ознакомиться.

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

аргумент

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

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

параметр

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

Существуют и другие синтаксисы параметров, например:

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

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

аргумент параметра

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

-f foo
--file foo

или включаться в тот же аргумент:

-ffoo
--file=foo

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

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

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

обязательный параметр

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

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

prog -v --report report.txt foo bar

-v и --report — это параметры. Если предположить, что --report принимает один аргумент, то report.txt — аргумент параметра. foo и bar — позиционные аргументы.

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

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

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

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

cp SOURCE DEST
cp SOURCE ... DEST-DIR

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

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

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

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

Короче говоря, старайтесь свести к минимуму количество сведений, которые пользователи обязаны указывать, и по возможности используйте разумные значения по умолчанию. Конечно, программы также должны быть достаточно гибкими. Для этого и нужны параметры. Неважно, представлены ли они записями в файле конфигурации, элементами управления в диалоговом окне «Настройки» графического интерфейса или параметрами командной строки: чем больше параметров вы реализуете, тем гибче программа и тем сложнее её реализация. Чрезмерная гибкость тоже имеет недостатки: слишком большое количество параметров может перегрузить пользователей и значительно усложнить сопровождение кода.

Руководство

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

Сначала нужно импортировать класс OptionParser; затем, в начале основной программы, создать экземпляр OptionParser:

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

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

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

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

Обычно для каждого параметра задаются одна короткая и одна длинная строка параметра, например:

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

Можно определить сколько угодно коротких и длинных строк параметров (в том числе ни одной), если в совокупности задана хотя бы одна строка параметра.

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

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

(options, args) = parser.parse_args()

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

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

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

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

Понимание действий параметров

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

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

Действие store

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

Например:

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

Теперь составим фиктивную командную строку и попросим optparse разобрать ее:

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

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

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

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

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

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

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

выведет 42.

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

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

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

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

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

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

Сначала рассмотрим пример с параметрами verbose/quiet. Если нужно, чтобы optparse присваивал verbose значение True, если не указан -q, можно сделать так:

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

Поскольку значения по умолчанию относятся к месту назначения, а не к какому-либо конкретному параметру, и у этих двух параметров одно и то же место назначения, это полностью эквивалентно следующему:

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

Рассмотрим такой пример:

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

И снова значением по умолчанию для verbose будет True: учитывается последнее значение по умолчанию, заданное для конкретного места назначения.

Более понятный способ задания значений по умолчанию — метод set_defaults() класса OptionParser, который можно вызвать в любой момент до вызова parse_args():

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

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

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

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

usage = "usage: %prog [options] arg1 arg2"
parser = OptionParser(usage=usage)
parser.add_option("-v", "--verbose",
                  action="store_true", dest="verbose", default=True,
                  help="make lots of noise [default]")
parser.add_option("-q", "--quiet",
                  action="store_false", dest="verbose",
                  help="be vewwy quiet (I'm hunting wabbits)")
parser.add_option("-f", "--filename",
                  metavar="FILE", help="write output to FILE")
parser.add_option("-m", "--mode",
                  default="intermediate",
                  help="interaction mode: novice, intermediate, "
                       "or expert [default: %default]")

Если optparse встретит в командной строке -h или --help либо если просто вызвать parser.print_help(), он выведет в стандартный поток вывода следующее:

Usage: <yourscript> [options] arg1 arg2

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

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

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

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

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

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

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

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

    -m MODE, --mode=MODE
    

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

    -f FILE, --filename=FILE
    

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

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

Группировка параметров

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

Группа параметров создается с помощью класса OptionGroup:

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

где

  • parser — экземпляр OptionParser, в который будет добавлена группа
  • title — заголовок группы
  • description, необязательный параметр, — подробное описание группы

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

После объявления всех параметров группа добавляется в ранее созданный анализатор с помощью его метода OptionParser add_option_group().

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

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

В результате будет выведена следующая справка:

Usage: <yourscript> [options] arg1 arg2

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

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

    -g                  Group option.

Более полный пример может включать несколько групп; продолжим предыдущий пример:

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

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

в результате будет получен следующий вывод:

Usage: <yourscript> [options] arg1 arg2

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

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

    -g                  Group option.

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

Еще один интересный метод, особенно полезный при программной работе с группами параметров:

OptionParser.get_option_group(opt_str)

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

Вывод строки версии

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

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

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

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

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

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

OptionParser.print_version(file=None)

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

OptionParser.get_version()

То же, что и print_version(), но возвращает строку версии, а не выводит ее.

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

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

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

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

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

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

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

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

Или случай, когда пользователь вообще не передает значение:

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

foo: error: -n option requires an argument

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

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

Собираем все вместе

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

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

if __name__ == "__main__":
    main()

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

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

Первый шаг при использовании optparse — создание экземпляра OptionParser.

class optparse.OptionParser(...)

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

usage (default: "%prog [options]")

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

option_list (default: [])

Список объектов Option, которыми нужно заполнить парсер. Параметры из option_list добавляются после параметров из standard_option_list (атрибута класса, который могут задавать подклассы OptionParser), но перед параметрами версии и справки. Устарело; вместо этого после создания парсера используйте add_option().

option_class (default: optparse.Option)

Класс, используемый при добавлении параметров в парсер с помощью add_option().

version (default: None)

Строка версии, выводимая, когда пользователь указывает параметр версии. Если для version указано истинное значение, optparse автоматически добавляет параметр версии с единственной строкой параметра --version. Подстрока %prog заменяется так же, как и для usage.

conflict_handler (default: "error")

Задает, что делать при добавлении в парсер параметров с конфликтующими строками параметров; см. раздел Конфликты между параметрами.

description (default: None)

Абзац с кратким обзором вашей программы. optparse форматирует этот абзац в соответствии с текущей шириной терминала и выводит его, когда пользователь запрашивает справку (после usage, но перед списком параметров).

formatter (default: a new IndentedHelpFormatter)

Экземпляр optparse.HelpFormatter, используемый для вывода текста справки. Для этой цели optparse предоставляет два конкретных класса: IndentedHelpFormatter и TitledHelpFormatter.

add_help_option (default: True)

Если значение истинно, optparse добавит в парсер параметр справки (со строками параметров -h и --help).

prog

Строка, используемая вместо os.path.basename(sys.argv[0]) при подстановке %prog в usage и version.

epilog (default: None)

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

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

Есть несколько способов добавить параметры в парсер. Рекомендуемый способ — использовать OptionParser.add_option(), как показано в разделе Руководство. add_option() можно вызвать одним из двух способов:

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

Другой вариант — передать конструктору OptionParser список предварительно созданных экземпляров Option, например:

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

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

Определение параметров

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

Стандартный способ создания экземпляра Option — метод add_option() класса OptionParser.

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

Чтобы определить параметр только с короткой строкой:

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

А чтобы определить параметр только с длинной строкой:

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

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

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

"store"

сохранить аргумент этого параметра (по умолчанию)

"store_const"

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

Option.type

(по умолчанию: "string")

Ожидаемый тип аргумента этого параметра (например, "string" или "int"); доступные типы параметров описаны здесь.

Option.dest

(по умолчанию: определяется по строкам параметров)

Если действие параметра подразумевает запись или изменение значения, этот атрибут указывает optparse, куда его записать: dest задает имя атрибута объекта options, который optparse создает при разборе командной строки.

Option.default

Значение, используемое для назначения этого параметра, если параметр отсутствует в командной строке. См. также OptionParser.set_defaults().

Option.nargs

(по умолчанию: 1)

Количество аргументов типа type, которые нужно обработать при обнаружении этого параметра. Если значение больше 1, optparse сохранит в dest кортеж значений.

Option.const

Для действий, сохраняющих постоянное значение, — значение, которое нужно сохранить.

Option.choices

Для параметров типа "choice" — список строк, из которых пользователь может выбрать.

Option.callback

Для параметров с действием "callback" — вызываемый объект, который нужно вызвать при обнаружении этого параметра. Подробнее об аргументах, передаваемых вызываемому объекту, см. в разделе Обратные вызовы параметров.

Option.callback_args
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, извлекается несколько аргументов, а в dest добавляется кортеж длиной nargs.

    Значения по умолчанию для type и dest такие же, как для действия "store".

    Пример:

    parser.add_option("-t", "--tracks", action="append", type="int")
    

    Если в командной строке встречается -t3, optparse выполняет эквивалент следующего:

    options.tracks = []
    options.tracks.append(int("3"))
    

    Если немного позже встречается --tracks=4, выполняется:

    options.tracks.append(int("4"))
    

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

    >>> parser.add_option("--files", action="append", default=['~/.mypkg/defaults'])
    >>> opts, args = parser.parse_args(['--files', 'overrides.mypkg'])
    >>> opts.files
    ['~/.mypkg/defaults', 'overrides.mypkg']
    
  • "append_const" [обязательный атрибут: const; относящийся атрибут: dest]

    Как "store_const", но значение const добавляется в dest; как и для "append", значение dest по умолчанию равно None, а пустой список автоматически создаётся при первом обнаружении параметра.

  • "count" [относящийся атрибут: dest]

    Увеличивает на единицу целое число, сохранённое в dest. Если значение по умолчанию не указано, перед первым увеличением для dest устанавливается значение 0.

    Пример:

    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, он выведет в stdout примерно такое справочное сообщение (при условии, что sys.argv[0] равно "foo.py"):

    Usage: foo.py [options]
    
    Options:
      -h, --help        Show this help message and exit
      -v                Be moderately verbose
      --file=FILENAME   Input file to read data from
    

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

  • "version"

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

Стандартные типы параметров

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

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

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

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

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

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

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

Разбор аргументов

Основная цель создания и заполнения OptionParser — вызов его метода parse_args().

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

Возвращает экземпляр 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" (default)

считать конфликты параметров ошибкой программирования и вызывать исключение OptionConflictError

"resolve"

интеллектуально разрешать конфликты параметров (см. ниже)

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

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

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

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

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

parser.add_option("--dry-run", ..., help="new dry-run option")

На этом этапе исходный параметр -n/--dry-run больше недоступен, поэтому optparse удаляет его, оставляя следующий текст справки:

Options:
  ...
  -n, --noisy   be noisy
  --dry-run     new dry-run option

Очистка

Экземпляры OptionParser содержат несколько циклических ссылок. Сборщик мусора Python должен корректно обработать их, однако при желании можно явно разорвать циклические ссылки, вызвав destroy() для OptionParser после завершения работы с ним. Это особенно полезно в долго работающих приложениях, где с OptionParser связаны большие графы объектов.

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

В OptionParser есть несколько других общедоступных методов:

OptionParser.set_usage(usage)

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

OptionParser.print_usage(file=None)

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

OptionParser.get_usage()

То же, что и print_usage(), но возвращает строку использования, а не выводит её.

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

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

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

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

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

Функции обратного вызова параметров

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

Чтобы определить параметр с функцией обратного вызова, нужно выполнить два шага:

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

Определение параметра с функцией обратного вызова

Как всегда, проще всего определить параметр с функцией обратного вызова с помощью метода OptionParser.add_option(). Помимо action, необходимо указать только один атрибут параметра — callback, вызываемую функцию:

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

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

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

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

Четыре аргумента функции обратного вызова описаны ниже.

При определении параметра с функцией обратного вызова можно указать и несколько других атрибутов параметра:

type

имеет обычное значение: как и для действий "store" или "append", он указывает optparse принять один аргумент и преобразовать его к типу type. Однако вместо сохранения преобразованных значений где-либо optparse передаёт их вашей функции обратного вызова.

nargs

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

callback_args

кортеж дополнительных позиционных аргументов, передаваемых функции обратного вызова

callback_kwargs

словарь дополнительных именованных аргументов, передаваемых функции обратного вызова

Вызов функций обратного вызова

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

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

где

option

экземпляр Option, вызывающий функцию обратного вызова

opt_str

строка параметра из командной строки, вызвавшая функцию обратного вызова. (Если использовался сокращённый длинный параметр, opt_str будет полной канонической строкой параметра: например, если пользователь укажет в командной строке --foo как сокращение для --foobar, то opt_str будет равно "--foobar".)

value

аргумент этого параметра из командной строки. optparse ожидает аргумент только в том случае, если задан type; тип value будет определяться типом параметра. Если для этого параметра type равен None (аргумент не ожидается), то 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:
        # 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 принимает один строковый аргумент, который без изменений передаётся методу error() класса OptionParser. Этот метод добавляет в начало имя программы и строку "error:", выводит всё это в stderr и завершает процесс.

Вот шуточный пример, показывающий, как добавить тип параметра "complex" для разбора комплексных чисел в стиле Python в командной строке. (Сейчас этот пример ещё нелепее, чем раньше, поскольку в версии 1.3 optparse появилась встроенная поддержка комплексных чисел, но неважно.)

Сначала необходимые импорты:

from copy import copy
from optparse import Option, OptionValueError

Сначала нужно определить функцию проверки типа, поскольку далее на неё будет ссылка (в атрибуте класса TYPE_CHECKER вашего подкласса Option):

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

Наконец, подкласс Option:

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

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

Готово! Теперь можно написать скрипт, использующий новый тип параметра, как и любой другой скрипт на основе optparse. Единственное отличие — нужно указать OptionParser использовать MyOption вместо Option:

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

Другой вариант — создать собственный список параметров и передать его в OptionParser; если не использовать add_option() описанным выше способом, сообщать OptionParser, какой класс параметров использовать, не потребуется:

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

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

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

Действия «сохранения»

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

Действия с типизированными значениями

действия, принимающие значение из командной строки и предполагающие, что оно имеет определённый тип; точнее, что строку можно преобразовать к определённому типу. Для таких параметров при создании Option необходимо указать атрибут type.

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

Добавляя действие, нужно отнести его к нужным категориям, указав его как минимум в одном из следующих атрибутов класса Option (все они представляют собой списки строк):

Option.ACTIONS

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

Option.STORE_ACTIONS

Действия «сохранения» дополнительно перечисляются здесь.

Option.TYPED_ACTIONS

Действия с типизированными значениями дополнительно перечисляются здесь.

Option.ALWAYS_TYPED_ACTIONS

Здесь дополнительно перечисляются действия, всегда принимающие значение определённого типа (то есть их параметры всегда принимают значение). Единственный эффект этого списка — присвоение optparse типа по умолчанию "string" параметрам без явно заданного типа, действие которых перечислено в ALWAYS_TYPED_ACTIONS.

Чтобы реализовать новое действие, необходимо переопределить метод take_action() класса Option и добавить в него обработку нового действия.

Например, добавим действие "extend". Оно похоже на стандартное действие "append", но вместо получения одного значения из командной строки и добавления его в существующий список действие "extend" принимает несколько значений в одной строке, разделённых запятыми, и добавляет их в существующий список. То есть если --names — это параметр "extend" типа "string", то при такой командной строке

--names=foo,bar --names blah --names ding,dong

получится список

["foo", "bar", "blah", "ding", "dong"]

Снова определим подкласс Option:

class MyOption(Option):

    ACTIONS = Option.ACTIONS + ("extend",)
    STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
    TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
    ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",)

    def take_action(self, action, dest, opt, value, values, parser):
        if action == "extend":
            lvalue = value.split(",")
            values.ensure_value(dest, []).extend(lvalue)
        else:
            Option.take_action(
                self, action, dest, opt, value, values, parser)

Обратите внимание на следующие особенности:

  • "extend" ожидает значение из командной строки и сохраняет его, поэтому это действие включено и в STORE_ACTIONS, и в TYPED_ACTIONS.
  • Чтобы optparse назначал действиям "extend" тип по умолчанию "string", мы также добавили действие "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, а затем возвращает 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

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

© 2001–2025 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.13/library/optparse.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API