optparse — Parser for command line options

Вихідний код: Lib/optparse.py

Застаріло починаючи з версії 3.2: The optparse module is deprecated and will not be developed further; development will continue with the argparse module.


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

As it parses the command line, optparse sets attributes of the options object returned by parse_args() based on user-supplied command-line values. When parse_args() returns from parsing this command line, options.filename will be "outfile" and options.verbose will be False. optparse supports both long and short options, allows short options to be merged together, and allows options to be associated with their arguments in a variety of ways. Thus, the following command lines are all equivalent to the above example:

<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 (це не те саме, що кілька параметрів, об’єднаних в один аргумент)

  • дефіс, за яким іде ціле слово, напр. -файл (технічно це еквівалент попереднього синтаксису, але вони зазвичай не зустрічаються в одній програмі)

  • знак плюс, після якого йде одна літера, або кілька літер, або слово, напр. +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()

(If you like, you can pass a custom argument list to parse_args(), but that’s rarely necessary: by default it uses sys.argv[1:].)

parse_args() returns two values:

  • options, об’єкт, що містить значення для всіх ваших параметрів — напр. якщо --file приймає один рядковий аргумент, options.file буде іменем файлу, наданим користувачем, або None, якщо користувач не вказав цей параметр

  • args, список позиційних аргументів, що залишилися після аналізу параметрів

Цей розділ посібника охоплює лише чотири найважливіші атрибути параметрів: action, type, dest (призначення) і help. З них action є найбільш фундаментальним.

Розуміння опціональних дій

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

Якщо ви не вкажете опцію дії, optparse за замовчуванням буде store.

Акція магазину

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

Наприклад:

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

Тепер давайте створимо фальшивий командний рядок і попросимо optparse розібрати його:

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

When optparse sees the option string -f, it consumes the next argument, foo.txt, and stores it in options.filename. So, after this call to parse_args(), options.filename is "foo.txt".

Деякі інші типи опцій, які підтримує optparse, це int і float. Ось варіант, який очікує цілочисельний аргумент:

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

Зауважте, що цей параметр не має довгого рядка параметрів, що цілком прийнятно. Крім того, немає явної дії, оскільки за замовчуванням є store.

Давайте розберемо ще один підроблений командний рядок. Цього разу ми зіткнемося з аргументом option прямо проти параметра: оскільки -n42 (один аргумент) еквівалентний -n 42 (два аргументи), код

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

надрукує 42.

Якщо ви не вкажете тип, optparse припускає рядок. У поєднанні з тим фактом, що типовою дією є 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"

store a constant value

"додати"

додати аргумент цього параметра до списку

"рахувати"

збільшити лічильник на одиницю

"зворотний виклик"

викликати вказану функцію

Вони описані в розділі Довідковий посібник і розділі Опція зворотних викликів.

Значення за замовчуванням

Усі наведені вище приклади включають встановлення деякої змінної («призначення»), коли відображаються певні параметри командного рядка. Що трапиться, якщо ці варіанти ніколи не побачать? Оскільки ми не вказали жодних значень за замовчуванням, для всіх встановлено значення 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: останнє значення за замовчуванням, надане для будь-якого конкретного призначення, є тим, яке враховується.

A clearer way to specify default values is the set_defaults() method of OptionParser, which you can call at any time before calling 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 використовує м’яке, але розумне значення за умовчанням: "Використання: %prog [параметри]", що добре, якщо ваш сценарій не приймає жодних позиційних аргументів.

  • кожен параметр визначає довідковий рядок і не турбується про перенесення рядків—optparse піклується про обтікання рядків і робить вихід довідки гарним.

  • options that take a value indicate this fact in their automatically-generated help message, e.g. for the «mode» option:

    -m MODE, --mode=MODE
    

    Here, «MODE» is called the meta-variable: it stands for the argument that the user is expected to supply to -m/--mode. By default, optparse converts the destination variable name to uppercase and uses that for the meta-variable. Sometimes, that’s not what you want—for example, the --filename option explicitly sets metavar="FILE", resulting in this automatically-generated option description:

    -f FILE, --filename=FILE
    

    Однак це важливо не тільки для економії місця: написаний вручну текст довідки використовує мета-змінну FILE, щоб зрозуміти користувачеві, що існує зв’язок між напівформальним синтаксисом -f 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. Окрім цього, версія може містити все, що завгодно. Коли ви вказуєте його, optparse автоматично додає опцію --version до вашого аналізатора. Якщо він зустрічає цей параметр у командному рядку, він розгортає ваш рядок version (шляхом заміни %prog), друкує його в stdout і завершує роботу.

Наприклад, якщо ваш скрипт називається /usr/bin/foo:

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

Наступні два методи можна використати для друку та отримання рядка version:

OptionParser.print_version(file=None)

Вивести повідомлення про версію для поточної програми (self.version) у файл (стандартний вивід за замовчуванням). Як і у випадку з print_usage(), будь-яке входження %prog у self.version замінюється назвою поточної програми. Нічого не робить, якщо self.version порожній або невизначений.

OptionParser.get_version()

Те саме, що print_version(), але повертає рядок версії замість її друку.

Як optparse обробляє помилки

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

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

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

У будь-якому випадку optparse обробляє помилку однаково: він друкує повідомлення про використання програми та повідомлення про помилку до стандартної помилки та виходить зі статусом помилки 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 не має обов’язкових аргументів, але має декілька необов’язкових ключових аргументів. Ви завжди повинні передавати їх як аргументи ключового слова, тобто не покладайтеся на порядок, у якому оголошено аргументи.

використання (за замовчуванням: "%prog [параметри]")

The usage summary to print when your program is run incorrectly or with a help option. When optparse prints the usage string, it expands %prog to os.path.basename(sys.argv[0]) (or to prog if you passed that keyword argument). To suppress a usage message, pass the special value optparse.SUPPRESS_USAGE.

option_list (за замовчуванням: [])

Список об’єктів Option для заповнення аналізатора. Опції в option_list додаються після будь-яких опцій в standard_option_list (атрибут класу, який може бути встановлений підкласами OptionParser), але перед будь-якою версією або опціями довідки. Застаріле; замість цього використовуйте add_option() після створення аналізатора.

option_class (за замовчуванням: optparse.Option)

Клас для використання під час додавання параметрів до аналізатора в add_option().

version (за замовчуванням: None)

Рядок версії для друку, коли користувач вказує параметр версії. Якщо ви вказуєте справжнє значення для version, optparse автоматично додає опцію версії з єдиним рядком опції --version. Підрядок %prog розгортається так само, як і usage.

conflict_handler (за замовчуванням: "помилка")

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

опис (за замовчуванням: None)

Абзац тексту, що дає короткий огляд вашої програми. optparse переформатує цей абзац відповідно до поточної ширини терміналу та друкує його, коли користувач запитує допомогу (після використання, але перед списком параметрів).

formatter (за замовчуванням: новий IndentedHelpFormatter)

Екземпляр optparse.HelpFormatter, який використовуватиметься для друку тексту довідки. optparse надає два конкретних класи для цієї мети: IndentedHelpFormatter і TitledHelpFormatter.

add_help_option (за замовчуванням: True)

Якщо істина, optparse додасть параметр довідки (із рядками параметрів -h і --help) до аналізатора.

програма

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

епілог (за замовчуванням: None)

Абзац тексту довідки для друку після довідки параметра.

Заповнення аналізатора

Є кілька способів заповнити аналізатор параметрами. Кращим способом є використання 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, пояснюючи вашу помилку.

Дія параметра визначає, що робить optparse, коли він зустрічає цей параметр у командному рядку. Стандартні дії параметрів, жорстко закодовані в optparse:

"магазин"

зберегти аргумент цього параметра (за замовчуванням)

"store_const"

store a constant value

"store_true"

зберігати Правда

"store_false"

зберігати False

"додати"

додати аргумент цього параметра до списку

"append_const"

append a constant value to a list

"рахувати"

збільшити лічильник на одиницю

"зворотний виклик"

викликати вказану функцію

"допомога"

роздрукувати повідомлення про використання, включно з усіма параметрами та документацією до них

(Якщо ви не вказали дію, за замовчуванням буде "store". Для цієї дії ви також можете вказати атрибути параметрів type і dest див. Стандартні опційні дії.)

As you can see, most actions involve storing or updating a value somewhere. optparse always creates a special object for this, conventionally called options (it happens to be an instance of optparse.Values). Option arguments (and various other values) are stored as attributes of this object, according to the dest (destination) option attribute.

Наприклад, коли ви дзвоните

parser.parse_args()

одна з перших речей, які робить optparse, це створює об’єкт options:

options = Values()

Якщо один із параметрів цього синтаксичного аналізатора визначено за допомогою

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

а командний рядок, що аналізується, містить будь-яке з наступного:

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

тоді optparse, побачивши цю опцію, зробить еквівалент:

options.filename = "foo"

Атрибути type і dest майже такі ж важливі, як і action, але action є єдиним такий, який має сенс для всіх варіантів.

Атрибути варіантів

Наступні атрибути параметрів можна передати як ключові аргументи до OptionParser.add_option(). Якщо ви передаєте атрибут опції, який не має відношення до певної опції, або не передаєте потрібний атрибут опції, optparse викликає OptionError.

Option.action

(за замовчуванням: "магазин")

Визначає поведінку optparse, коли цей параметр відображається в командному рядку; доступні параметри задокументовані тут.

Option.type

(за замовчуванням: "рядок")

Тип аргументу, очікуваний цією опцією (наприклад, "string" або "int"); доступні типи опцій задокументовані тут.

Option.dest

(за замовчуванням: отримано з рядків параметрів)

Якщо дія опції передбачає запис або зміну значення десь, це вказує optparse, де його писати: dest називає атрибут об’єкта options, який optparse збирається, коли аналізує командний рядок.

Option.default

Значення для призначення цього параметра, якщо параметр не відображається в командному рядку. Дивіться також OptionParser.set_defaults().

Option.nargs

(за замовчуванням: 1)

Скільки аргументів типу type має споживатися, коли відображається цей параметр. Якщо > 1, optparse зберігатиме кортеж значень у dest.

Option.const

Для дій, які зберігають постійне значення, постійне значення для збереження.

Option.choices

Для параметрів типу "вибір", список рядків, з яких користувач може вибрати.

Option.callback

Для параметрів із дією "callback", виклик якого потрібно викликати, коли цей параметр видно. Дивіться розділ Опція зворотних викликів для детальної інформації про аргументи, які передаються викликаному.

Option.callback_args
Option.callback_kwargs

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

Option.help

Help text to print for this option when listing all available options after the user supplies a help option (such as --help). If no help text is supplied, the option will be listed without help text. To hide this option, use the special value optparse.SUPPRESS_HELP.

Option.metavar

(за замовчуванням: отримано з рядків параметрів)

Заміна аргументу(ів) опції для використання під час друку довідкового тексту. Перегляньте розділ Підручник для прикладу.

Стандартні опційні дії

Усі різні опціональні дії мають дещо різні вимоги та наслідки. Більшість дій мають кілька відповідних атрибутів параметрів, які ви можете вказати, щоб керувати поведінкою optparse; деякі з них мають обов’язкові атрибути, які ви повинні вказати для будь-якої опції, що використовує цю дію.

  • "магазин" [релевантний: 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 для поточного значення опції. Це означає, що будь-яке вказане значення за замовчуванням повинно мати метод додавання. Це також означає, що якщо значення за замовчуванням не є порожнім, елементи за замовчуванням будуть присутні в розібраному значенні для параметра, а будь-які значення з командного рядка будуть додані після цих значень за замовчуванням:

    >>> 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" [relevant: 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)
    

    Дивіться розділ Опція зворотних викликів для більш детальної інформації.

  • "допомога"

    Друкує повне довідкове повідомлення для всіх параметрів у поточному аналізаторі параметрів. Повідомлення довідки складається з рядка usage, переданого конструктору OptionParser, і рядка help, переданого кожному параметру.

    If no help string is supplied for an option, it will still be listed in the help message. To omit an option entirely, use the special value 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"):

    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).

  • "версія"

    Друкує номер версії, наданий OptionParser, у stdout і завершує роботу. Номер версії фактично форматується та друкується методом print_version() OptionParser. Зазвичай актуально, лише якщо аргумент version надається конструктору OptionParser. Як і у випадку з параметрами help, ви рідко будете створювати параметри version, оскільки optparse автоматично додає їх за потреби.

Типи стандартних варіантів

optparse має п’ять вбудованих типів параметрів: "string", "int", "choice", "float" і "complex ". Якщо вам потрібно додати нові типи опцій, перегляньте розділ Розширення optparse.

Аргументи параметрів рядка не перевіряються та не перетворюються жодним чином: текст у командному рядку зберігається в місці призначення (або передається зворотному виклику) як є.

Цілі аргументи (тип "int") аналізуються таким чином:

  • якщо число починається з 0x, воно аналізується як шістнадцяткове число

  • якщо число починається з 0, воно аналізується як вісімкове число

  • якщо число починається з 0b, воно аналізується як двійкове число

  • інакше число аналізується як десяткове число

Перетворення виконується викликом int() із відповідною основою (2, 8, 10 або 16). Якщо це не вдасться, не вийде і optparse, хоча з більш корисним повідомленням про помилку.

Аргументи параметрів "float" і "complex" перетворюються безпосередньо за допомогою float() і complex(), з подібною обробкою помилок.

Опції "choice" є підтипом опцій "string". Атрибут опції choices (послідовність рядків) визначає набір дозволених аргументів опції. optparse.check_choice() порівнює аргументи параметрів, надані користувачем, із цим головним списком і викликає OptionValueError, якщо вказано недійсний рядок.

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

The whole point of creating and populating an OptionParser is to call its parse_args() method:

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

where the input parameters are

args

список аргументів для обробки (за замовчуванням: sys.argv[1:])

значення

an optparse.Values object to store option arguments in (default: a new instance of Values) – if you give an existing object, the option defaults will not be initialized on it

and the return values are

параметри

the same object that was passed in as values, or the optparse.Values instance created by optparse

args

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

The most common usage is to supply neither keyword argument. If you supply values, it will be modified with repeated setattr() calls (roughly one for every option argument stored to an option destination) and returned by parse_args().

If parse_args() encounters any errors in the argument list, it calls the OptionParser’s error() method with an appropriate end-user error message. This ultimately terminates your process with an exit status of 2 (the traditional Unix exit status for command-line errors).

Запити та маніпулювання вашим аналізатором параметрів

Поведінку аналізатора параметрів за замовчуванням можна дещо налаштувати, і ви також можете пошукати свій аналізатор параметрів і подивитися, що там є. 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)

Доступні засоби обробки конфліктів:

"помилка" (за замовчуванням)

припустити, що конфлікти параметрів є помилкою програмування, і викликати OptionConflictError

"розв'язати"

розумно вирішувати конфлікти варіантів (див. нижче)

Як приклад, давайте визначимо OptionParser, який розумно вирішує конфлікти, і додамо до нього конфліктуючі параметри:

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

At this point, optparse detects that a previously-added option is already using the -n option string. Since conflict_handler is "resolve", it resolves the situation by removing -n from the earlier option’s list of option strings. Now --dry-run is the only way for the user to activate that option. If the user asks for help, the help message will reflect that:

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

It’s possible to whittle away the option strings for a previously-added option until there are none left, and the user has no way of invoking that option from the command-line. In that case, optparse removes that option completely, so it doesn’t show up in help text or anywhere else. Carrying on with our existing 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)

Set the usage string according to the rules described above for the usage constructor keyword argument. Passing None sets the default usage string; use optparse.SUPPRESS_USAGE to suppress a usage message.

OptionParser.print_usage(file=None)

Надрукувати повідомлення про використання для поточної програми (self.usage) у файл (стандартний вихід за замовчуванням). Будь-яке входження рядка %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, який викликає зворотний виклик

opt_str

це рядок параметрів, який можна побачити в командному рядку, який запускає зворотний виклик. (Якщо використовувався скорочений довгий параметр, opt_str буде повним, канонічним рядком параметра — наприклад, якщо користувач розміщує --foo у командному рядку як скорочення для -- foobar, тоді opt_str буде "--foobar".)

значення

є аргументом цього параметра в командному рядку. optparse очікуватиме аргумент, лише якщо встановлено type; тип значення буде типом, який передбачається типом опції. Якщо type для цього параметра має значення None (аргумент не очікується), тоді value буде None. Якщо nargs > 1, value буде кортежем значень відповідного типу.

парсер

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

parser.largs

the current list of leftover arguments, ie. arguments that have been consumed but are neither options nor option arguments. Feel free to modify parser.largs, e.g. by adding more arguments to it. (This list will become args, the second return value of parse_args().)

parser.rargs

поточний список аргументів, що залишилися, тобто. з вилученими параметрами opt_str і value (якщо застосовно), і залишаються лише наступні за ними аргументи. Не соромтеся змінити parser.rargs, напр. споживаючи більше аргументів.

parser.values

об’єкт, де за замовчуванням зберігаються значення параметрів (екземпляр optparse.OptionValues). Це дозволяє зворотним викликам використовувати той самий механізм, що й решта optparse для зберігання значень параметрів; вам не потрібно возитися з глобалами чи закриттями. Ви також можете отримати доступ або змінити значення будь-яких параметрів, які вже зустрічаються в командному рядку.

args

це кортеж довільних позиційних аргументів, що надаються через атрибут опції callback_args.

кварги

це словник довільних аргументів ключових слів, які надаються через 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: перевірка порядку опцій (узагальнено)

If you want to re-use this callback for several similar options (set a flag, but blow up if -b has already been seen), it needs a bit of work: the error message and the flag that it sets must be generalized.

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, який, у свою чергу, додає назву програми та рядок "помилка: " і друкує все в 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 параметра optparse Оскільки це Python, ніщо не заважає вам це зробити, крім хороших манер і здорового глузду.)

Це воно! Тепер ви можете написати сценарій, який використовує новий тип опцій, як і будь-який інший сценарій на основі optparse, за винятком того, що вам потрібно вказати вашому OptionParser використовувати MyOption замість Option:

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

Крім того, ви можете створити власний список параметрів і передати його в OptionParser; якщо ви не використовуєте add_option() вищезгаданим способом, вам не потрібно вказувати OptionParser, який клас параметрів використовувати:

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

Додавання нових дій

Додавати нові дії трохи складніше, тому що ви повинні розуміти, що optparse має кілька класифікацій для дій:

дії «магазину».

дії, які призводять до того, що optparse зберігає значення в атрибуті поточного екземпляра OptionValues; ці параметри вимагають надання атрибута dest конструктору Option.

«набрані» дії

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

Це набори, що перекриваються: деякі дії «зберігання» за замовчуванням - це "store", "store_const", "append" і "count", а за замовчуванням «typed» » діями є "зберігати", "додавати" і "зворотний виклик".

Коли ви додаєте дію, вам потрібно класифікувати її, перерахувавши принаймні в одному з наступних атрибутів класу Option (усі є списками рядків):

Option.ACTIONS

Усі дії мають бути вказані в ACTIONS.

Option.STORE_ACTIONS

тут додатково перераховані дії «магазину».

Option.TYPED_ACTIONS

«введені» дії додатково перераховані тут.

Option.ALWAYS_TYPED_ACTIONS

Дії, які завжди мають тип (тобто чиї параметри завжди приймають значення), додатково перераховані тут. Єдиним ефектом цього є те, що optparse призначає тип за замовчуванням, "string", параметрам без явного типу, дія яких указана в ALWAYS_TYPED_ACTIONS.

Щоб фактично реалізувати вашу нову дію, ви повинні перевизначити метод take_action() Option і додати регістр, який розпізнає вашу дію.

Наприклад, давайте додамо дію "розширити". Це схоже на стандартну дію "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)
    

    If the attr attribute of values doesn’t exist or is None, then ensure_value() first sets it to value, and then returns „value. This is very handy for actions like "extend", "append", and "count", all of which accumulate data in a variable and expect that variable to be of a certain type (a list for the first two, an integer for the latter). Using ensure_value() means that scripts using your action don’t have to worry about setting a default value for the option destinations in question; they can just leave the default as None and ensure_value() will take care of getting it right when it’s needed.