argparse.md · Markdown – Документация Python
Документация Python неофициальный перевод

argparse.md

672 строк · 29.9 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.5/howto/argparse.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Руководство по Argparse89| автор: | Tshepang Lekhonkhobe |10| --- | --- |1112Это руководство задумано как мягкое введение в [`argparse`](https://python-all.ru/3.5/library/argparse.html#module-argparse), рекомендуемый модуль для разбора командной строки в стандартной библиотеке Python.1314> **Примечание**15>16> Существуют ещё два модуля, выполняющие ту же задачу, а именно [`getopt`](https://python-all.ru/3.5/library/getopt.html#module-getopt) (аналог `getopt()` из языка C ) и устаревший [`optparse`](https://python-all.ru/3.5/library/optparse.html#module-optparse). Обратите также внимание, что [`argparse`](https://python-all.ru/3.5/library/argparse.html#module-argparse) основан на [`optparse`](https://python-all.ru/3.5/library/optparse.html#module-optparse), и поэтому очень похож по использованию.1718## Основные понятия1920Давайте покажем, какие возможности мы будем изучать в этом вводном руководстве, на примере команды **ls**:2122```sh23$ ls24cpython  devguide  prog.py  pypy  rm-unused-function.patch25$ ls pypy26ctypes_configure  demo  dotviewer  include  lib_pypy  lib-python ...27$ ls -l28total 2029drwxr-xr-x 19 wena wena 4096 Feb 18 18:51 cpython30drwxr-xr-x  4 wena wena 4096 Feb  8 12:04 devguide31-rwxr-xr-x  1 wena wena  535 Feb 19 00:05 prog.py32drwxr-xr-x 14 wena wena 4096 Feb  7 00:59 pypy33-rw-r--r--  1 wena wena  741 Feb 18 01:01 rm-unused-function.patch34$ ls --help35Usage: ls [OPTION]... [FILE]...36List information about the FILEs (the current directory by default).37Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.38...39```4041Из этих четырёх команд можно извлечь несколько понятий:4243- Команда **ls** полезна при запуске без каких-либо опций. По умолчанию она выводит содержимое текущего каталога.44- Если нужно больше, чем даётся по умолчанию, мы сообщаем программе дополнительные сведения. В данном случае мы хотим показать другой каталог – `pypy`. Мы указали так называемый позиционный аргумент. Он назван так потому, что программа понимает, что делать со значением, только по его позиции в командной строке. Это понятие лучше видно на примере команды **cp**, простейшее использование которой – `cp SRC DEST`. Первая позиция – *что нужно скопировать*, а вторая – *куда скопировать*.45- Теперь представим, что мы хотим изменить поведение программы. В нашем примере мы выводим больше информации о каждом файле, а не только имена. `-l` в этом случае называется необязательным аргументом.46- Это фрагмент справки. Она очень полезна: вы можете встретить незнакомую программу и понять, как она работает, просто прочитав её справку.4748## Основы4950Начнём с очень простого примера, который (почти) ничего не делает:5152```python53import argparse54parser = argparse.ArgumentParser()55parser.parse_args()56```5758Ниже приведён результат выполнения кода:5960```sh61$ python3 prog.py62$ python3 prog.py --help63usage: prog.py [-h]6465optional arguments:66  -h, --help  show this help message and exit67$ python3 prog.py --verbose68usage: prog.py [-h]69prog.py: error: unrecognized arguments: --verbose70$ python3 prog.py foo71usage: prog.py [-h]72prog.py: error: unrecognized arguments: foo73```7475Вот что происходит:7677- Запуск скрипта без опций не выводит ничего в stdout. Не очень полезно.78- Второй запуск начинает показывать полезность модуля [`argparse`](https://python-all.ru/3.5/library/argparse.html#module-argparse). Мы почти ничего не сделали, но уже получили хорошее сообщение справки.79- Опция `--help`, которую можно сократить до `-h`, – единственная опция, которую мы получаем бесплатно (т.е. её не нужно указывать). Всё остальное приводит к ошибке. Но даже в этом случае мы получаем полезное сообщение об использовании – тоже бесплатно.8081## Знакомство с позиционными аргументами8283Пример:8485```python86import argparse87parser = argparse.ArgumentParser()88parser.add_argument("echo")89args = parser.parse_args()90print(args.echo)91```9293И запуск кода:9495```sh96$ python3 prog.py97usage: prog.py [-h] echo98prog.py: error: the following arguments are required: echo99$ python3 prog.py --help100usage: prog.py [-h] echo101102positional arguments:103  echo104105optional arguments:106  -h, --help  show this help message and exit107$ python3 prog.py foo108foo109```110111Вот что происходит:112113- Мы добавили метод `add_argument()`, который используется для указания опций командной строки, которые программа готова принять. В данном случае я назвал его `echo`, чтобы оно соответствовало своей функции.114- Теперь для вызова программы требуется указать опцию.115- Метод `parse_args()` на самом деле возвращает некоторые данные из указанных опций, в данном случае `echo`.116- Переменная – это своего рода «магия», которую [`argparse`](https://python-all.ru/3.5/library/argparse.html#module-argparse) выполняет бесплатно (т.е. не нужно указывать, в какой переменной хранится это значение). Вы также заметите, что её имя совпадает со строковым аргументом, переданным методу – `echo`.117118Однако обратите внимание, что, хотя справка выглядит красиво, пока она не так полезна, как могла бы быть. Например, мы видим, что у нас есть позиционный аргумент `echo`, но не знаем, что он делает – только догадываемся или читаем исходный код. Давайте сделаем его немного полезнее:119120```python121import argparse122parser = argparse.ArgumentParser()123parser.add_argument("echo", help="echo the string you use here")124args = parser.parse_args()125print(args.echo)126```127128И получаем:129130```sh131$ python3 prog.py -h132usage: prog.py [-h] echo133134positional arguments:135  echo        echo the string you use here136137optional arguments:138  -h, --help  show this help message and exit139```140141А теперь давайте сделаем что-нибудь ещё более полезное:142143```python144import argparse145parser = argparse.ArgumentParser()146parser.add_argument("square", help="display a square of a given number")147args = parser.parse_args()148print(args.square**2)149```150151Ниже приведён результат выполнения кода:152153```sh154$ python3 prog.py 4155Traceback (most recent call last):156  File "prog.py", line 5, in <module>157    print(args.square**2)158TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'159```160161Всё пошло не так. Это потому, что [`argparse`](https://python-all.ru/3.5/library/argparse.html#module-argparse) воспринимает переданные ему параметры как строки, если не указать иное. Итак, укажем [`argparse`](https://python-all.ru/3.5/library/argparse.html#module-argparse) воспринимать ввод как целое число:162163```python164import argparse165parser = argparse.ArgumentParser()166parser.add_argument("square", help="display a square of a given number",167                    type=int)168args = parser.parse_args()169print(args.square**2)170```171172Ниже приведён результат выполнения кода:173174```sh175$ python3 prog.py 417616177$ python3 prog.py four178usage: prog.py [-h] square179prog.py: error: argument square: invalid int value: 'four'180```181182Всё прошло хорошо. Программа теперь даже корректно завершается при неверном вводе перед продолжением.183184## Знакомство с необязательными аргументами185186До сих пор мы работали с позиционными аргументами. Давайте посмотрим, как добавить необязательные.187188```python189import argparse190parser = argparse.ArgumentParser()191parser.add_argument("--verbosity", help="increase output verbosity")192args = parser.parse_args()193if args.verbosity:194    print("verbosity turned on")195```196197И вывод:198199```sh200$ python3 prog.py --verbosity 1201verbosity turned on202$ python3 prog.py203$ python3 prog.py --help204usage: prog.py [-h] [--verbosity VERBOSITY]205206optional arguments:207  -h, --help            show this help message and exit208  --verbosity VERBOSITY209                        increase output verbosity210$ python3 prog.py --verbosity211usage: prog.py [-h] [--verbosity VERBOSITY]212prog.py: error: argument --verbosity: expected one argument213```214215Вот что происходит:216217- Программа написана так, чтобы выводить что-то, когда указан `--verbosity`, и ничего не выводить, если не указан.218- Чтобы показать, что опция действительно необязательна, при запуске программы без неё ошибки не возникает. Обратите внимание: по умолчанию, если необязательный аргумент не указан, соответствующая переменная (в данном случае `args.verbosity`) получает значение `None`, из-за чего она не проходит проверку на истинность в операторе [`if`](https://python-all.ru/3.5/reference/compound_stmts.html#if).219- Справочное сообщение немного отличается.220- При использовании опции `--verbosity` необходимо также указать некоторое значение, любое значение.221222В приведённом выше примере `--verbosity` принимает любые целые числа, но для нашей простой программы на самом деле полезны только два значения: `True` или `False`. Давайте соответствующим образом изменим код:223224```python225import argparse226parser = argparse.ArgumentParser()227parser.add_argument("--verbose", help="increase output verbosity",228                    action="store_true")229args = parser.parse_args()230if args.verbose:231    print("verbosity turned on")232```233234И вывод:235236```sh237$ python3 prog.py --verbose238verbosity turned on239$ python3 prog.py --verbose 1240usage: prog.py [-h] [--verbose]241prog.py: error: unrecognized arguments: 1242$ python3 prog.py --help243usage: prog.py [-h] [--verbose]244245optional arguments:246  -h, --help  show this help message and exit247  --verbose   increase output verbosity248```249250Вот что происходит:251252- Теперь опция больше напоминает флаг, нежели что-то, требующее значения. Мы даже изменили имя опции в соответствии с этой идеей. Обратите внимание: теперь мы указываем новый ключевой аргумент `action` и присваиваем ему значение `"store_true"`. Это означает, что если опция указана, то `args.verbose` присваивается значение `True`. Если не указана – то `False`.253- Программа выдаёт ошибку, если указано значение, в полном соответствии с тем, что такое флаги на самом деле.254- Обратите внимание на другой текст справки.255256### Короткие опции257258Если вы знакомы с работой из командной строки, то заметили, что я ещё не касался темы коротких версий опций. Всё довольно просто:259260```python261import argparse262parser = argparse.ArgumentParser()263parser.add_argument("-v", "--verbose", help="increase output verbosity",264                    action="store_true")265args = parser.parse_args()266if args.verbose:267    print("verbosity turned on")268```269270И вот:271272```sh273$ python3 prog.py -v274verbosity turned on275$ python3 prog.py --help276usage: prog.py [-h] [-v]277278optional arguments:279  -h, --help     show this help message and exit280  -v, --verbose  increase output verbosity281```282283Обратите внимание, что новая возможность также отражена в справочном тексте.284285## Сочетание позиционных и необязательных аргументов286287Наша программа становится всё сложнее:288289```python290import argparse291parser = argparse.ArgumentParser()292parser.add_argument("square", type=int,293                    help="display a square of a given number")294parser.add_argument("-v", "--verbose", action="store_true",295                    help="increase output verbosity")296args = parser.parse_args()297answer = args.square**2298if args.verbose:299    print("the square of {} equals {}".format(args.square, answer))300else:301    print(answer)302```303304А теперь вывод:305306```sh307$ python3 prog.py308usage: prog.py [-h] [-v] square309prog.py: error: the following arguments are required: square310$ python3 prog.py 431116312$ python3 prog.py 4 --verbose313the square of 4 equals 16314$ python3 prog.py --verbose 4315the square of 4 equals 16316```317318- Мы вернули позиционный аргумент, отсюда и жалоба.319- Обратите внимание: порядок не важен.320321А что, если вернуть нашей программе возможность иметь несколько значений уровня подробности вывода и на самом деле их использовать:322323```python324import argparse325parser = argparse.ArgumentParser()326parser.add_argument("square", type=int,327                    help="display a square of a given number")328parser.add_argument("-v", "--verbosity", type=int,329                    help="increase output verbosity")330args = parser.parse_args()331answer = args.square**2332if args.verbosity == 2:333    print("the square of {} equals {}".format(args.square, answer))334elif args.verbosity == 1:335    print("{}^2 == {}".format(args.square, answer))336else:337    print(answer)338```339340И вывод:341342```sh343$ python3 prog.py 434416345$ python3 prog.py 4 -v346usage: prog.py [-h] [-v VERBOSITY] square347prog.py: error: argument -v/--verbosity: expected one argument348$ python3 prog.py 4 -v 13494^2 == 16350$ python3 prog.py 4 -v 2351the square of 4 equals 16352$ python3 prog.py 4 -v 335316354```355356Все они выглядят хорошо, кроме последнего, который выявляет ошибку в нашей программе. Давайте исправим её, ограничив значения, которые может принимать опция `--verbosity`:357358```python359import argparse360parser = argparse.ArgumentParser()361parser.add_argument("square", type=int,362                    help="display a square of a given number")363parser.add_argument("-v", "--verbosity", type=int, choices=[0, 1, 2],364                    help="increase output verbosity")365args = parser.parse_args()366answer = args.square**2367if args.verbosity == 2:368    print("the square of {} equals {}".format(args.square, answer))369elif args.verbosity == 1:370    print("{}^2 == {}".format(args.square, answer))371else:372    print(answer)373```374375И вывод:376377```sh378$ python3 prog.py 4 -v 3379usage: prog.py [-h] [-v {0,1,2}] square380prog.py: error: argument -v/--verbosity: invalid choice: 3 (choose from 0, 1, 2)381$ python3 prog.py 4 -h382usage: prog.py [-h] [-v {0,1,2}] square383384positional arguments:385  square                display a square of a given number386387optional arguments:388  -h, --help            show this help message and exit389  -v {0,1,2}, --verbosity {0,1,2}390                        increase output verbosity391```392393Обратите внимание: изменение также отражается как в сообщении об ошибке, так и в строке справки.394395Теперь давайте применим другой подход к работе с подробностью вывода, который довольно распространён. Он также соответствует тому, как исполняемый файл CPython обрабатывает собственный аргумент подробности (проверьте вывод `python --help`):396397```python398import argparse399parser = argparse.ArgumentParser()400parser.add_argument("square", type=int,401                    help="display the square of a given number")402parser.add_argument("-v", "--verbosity", action="count",403                    help="increase output verbosity")404args = parser.parse_args()405answer = args.square**2406if args.verbosity == 2:407    print("the square of {} equals {}".format(args.square, answer))408elif args.verbosity == 1:409    print("{}^2 == {}".format(args.square, answer))410else:411    print(answer)412```413414Введено ещё одно действие – “count”, для подсчёта количества вхождений определённых необязательных аргументов:415416```sh417$ python3 prog.py 441816419$ python3 prog.py 4 -v4204^2 == 16421$ python3 prog.py 4 -vv422the square of 4 equals 16423$ python3 prog.py 4 --verbosity --verbosity424the square of 4 equals 16425$ python3 prog.py 4 -v 1426usage: prog.py [-h] [-v] square427prog.py: error: unrecognized arguments: 1428$ python3 prog.py 4 -h429usage: prog.py [-h] [-v] square430431positional arguments:432  square           display a square of a given number433434optional arguments:435  -h, --help       show this help message and exit436  -v, --verbosity  increase output verbosity437$ python3 prog.py 4 -vvv43816439```440441- Да, теперь это больше похоже на флаг (аналогично `action="store_true"` в предыдущей версии нашего скрипта). Этим и объясняется жалоба.442- Кроме того, оно ведёт себя аналогично действию «store\_true».443- А вот демонстрация того, что даёт действие «count». Вы, вероятно, уже встречали подобное использование.444- А если не указывать флаг `-v`, считается, что этот флаг имеет значение `None`.445- Как и следовало ожидать, при указании длинной формы флага мы получим тот же результат.446- К сожалению, наш вывод справки не очень информативен о новых возможностях скрипта, но это всегда можно исправить, улучшив документацию (например, через именованный аргумент `help`).447- Последний вывод обнаруживает ошибку в нашей программе.448449Исправим:450451```python452import argparse453parser = argparse.ArgumentParser()454parser.add_argument("square", type=int,455                    help="display a square of a given number")456parser.add_argument("-v", "--verbosity", action="count",457                    help="increase output verbosity")458args = parser.parse_args()459answer = args.square**2460461# исправление ошибки: заменить == на >=462if args.verbosity >= 2:463    print("the square of {} equals {}".format(args.square, answer))464elif args.verbosity >= 1:465    print("{}^2 == {}".format(args.square, answer))466else:467    print(answer)468```469470И вот что получается:471472```sh473$ python3 prog.py 4 -vvv474the square of 4 equals 16475$ python3 prog.py 4 -vvvv476the square of 4 equals 16477$ python3 prog.py 4478Traceback (most recent call last):479  File "prog.py", line 11, in <module>480    if args.verbosity >= 2:481TypeError: unorderable types: NoneType() >= int()482```483484- Первый вывод прошёл хорошо и исправляет предыдущую ошибку. То есть мы хотим, чтобы любое значение \>= 2 давало максимально подробный вывод.485- Третий вывод уже не так хорош.486487Исправим и эту ошибку:488489```python490import argparse491parser = argparse.ArgumentParser()492parser.add_argument("square", type=int,493                    help="display a square of a given number")494parser.add_argument("-v", "--verbosity", action="count", default=0,495                    help="increase output verbosity")496args = parser.parse_args()497answer = args.square**2498if args.verbosity >= 2:499    print("the square of {} equals {}".format(args.square, answer))500elif args.verbosity >= 1:501    print("{}^2 == {}".format(args.square, answer))502else:503    print(answer)504```505506Мы только что ввели ещё один именованный аргумент – `default`. Мы установили его в `0`, чтобы можно было сравнивать с другими целочисленными значениями. Помните: по умолчанию, если необязательный аргумент не указан, он получает значение `None`, и такое значение нельзя сравнить с целым числом (отсюда исключение [`TypeError`](https://python-all.ru/3.5/library/exceptions.html#TypeError)).507508И:509510```sh511$ python3 prog.py 451216513```514515Уже с тем, что мы узнали, можно уйти довольно далеко, а мы только коснулись поверхности. Модуль [`argparse`](https://python-all.ru/3.5/library/argparse.html#module-argparse) очень мощный, и мы рассмотрим его чуть подробнее, прежде чем завершить этот учебник.516517## Немного более продвинутый материал518519Что, если бы мы захотели расширить нашу крошечную программу, чтобы она вычисляла не только квадраты, но и другие степени:520521```python522import argparse523parser = argparse.ArgumentParser()524parser.add_argument("x", type=int, help="the base")525parser.add_argument("y", type=int, help="the exponent")526parser.add_argument("-v", "--verbosity", action="count", default=0)527args = parser.parse_args()528answer = args.x**args.y529if args.verbosity >= 2:530    print("{} to the power {} equals {}".format(args.x, args.y, answer))531elif args.verbosity >= 1:532    print("{}^{} == {}".format(args.x, args.y, answer))533else:534    print(answer)535```536537Вывод:538539```sh540$ python3 prog.py541usage: prog.py [-h] [-v] x y542prog.py: error: the following arguments are required: x, y543$ python3 prog.py -h544usage: prog.py [-h] [-v] x y545546positional arguments:547  x                the base548  y                the exponent549550optional arguments:551  -h, --help       show this help message and exit552  -v, --verbosity553$ python3 prog.py 4 2 -v5544^2 == 16555```556557Обратите внимание: до сих пор мы использовали уровень подробности, чтобы *изменять* выводимый текст. В следующем примере уровень подробности используется, чтобы выводить *больше* текста:558559```python560import argparse561parser = argparse.ArgumentParser()562parser.add_argument("x", type=int, help="the base")563parser.add_argument("y", type=int, help="the exponent")564parser.add_argument("-v", "--verbosity", action="count", default=0)565args = parser.parse_args()566answer = args.x**args.y567if args.verbosity >= 2:568    print("Running '{}'".format(__file__))569if args.verbosity >= 1:570    print("{}^{} == ".format(args.x, args.y), end="")571print(answer)572```573574Вывод:575576```sh577$ python3 prog.py 4 257816579$ python3 prog.py 4 2 -v5804^2 == 16581$ python3 prog.py 4 2 -vv582Running 'prog.py'5834^2 == 16584```585586### Конфликтующие опции587588До сих пор мы работали с двумя методами экземпляра [`argparse.ArgumentParser`](https://python-all.ru/3.5/library/argparse.html#argparse.ArgumentParser). Познакомимся с третьим – `add_mutually_exclusive_group()`. Он позволяет указывать опции, которые противоречат друг другу. Давайте также изменим остальную часть программы, чтобы новая функциональность стала более осмысленной: мы введём опцию `--quiet`, которая будет противоположностью опции `--verbose`:589590```python591import argparse592593parser = argparse.ArgumentParser()594group = parser.add_mutually_exclusive_group()595group.add_argument("-v", "--verbose", action="store_true")596group.add_argument("-q", "--quiet", action="store_true")597parser.add_argument("x", type=int, help="the base")598parser.add_argument("y", type=int, help="the exponent")599args = parser.parse_args()600answer = args.x**args.y601602if args.quiet:603    print(answer)604elif args.verbose:605    print("{} to the power {} equals {}".format(args.x, args.y, answer))606else:607    print("{}^{} == {}".format(args.x, args.y, answer))608```609610Наша программа теперь проще, и ради демонстрации мы потеряли часть функциональности. В любом случае, вот вывод:611612```sh613$ python3 prog.py 4 26144^2 == 16615$ python3 prog.py 4 2 -q61616617$ python3 prog.py 4 2 -v6184 to the power 2 equals 16619$ python3 prog.py 4 2 -vq620usage: prog.py [-h] [-v | -q] x y621prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose622$ python3 prog.py 4 2 -v --quiet623usage: prog.py [-h] [-v | -q] x y624prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose625```626627Это должно быть легко понять. Я добавил последний вывод, чтобы вы могли увидеть, какую гибкость это даёт: например, смешивание длинной и короткой форм опций.628629Прежде чем закончить, вы, вероятно, захотите сообщить пользователям основное назначение вашей программы, на случай если они не знают:630631```python632import argparse633634parser = argparse.ArgumentParser(description="calculate X to the power of Y")635group = parser.add_mutually_exclusive_group()636group.add_argument("-v", "--verbose", action="store_true")637group.add_argument("-q", "--quiet", action="store_true")638parser.add_argument("x", type=int, help="the base")639parser.add_argument("y", type=int, help="the exponent")640args = parser.parse_args()641answer = args.x**args.y642643if args.quiet:644    print(answer)645elif args.verbose:646    print("{} to the power {} equals {}".format(args.x, args.y, answer))647else:648    print("{}^{} == {}".format(args.x, args.y, answer))649```650651Обратите внимание на небольшое различие в тексте использования. Обратите внимание на `[-v | -q]`, который сообщает, что мы можем использовать либо `-v`, либо `-q`, но не оба одновременно:652653```sh654$ python3 prog.py --help655usage: prog.py [-h] [-v | -q] x y656657calculate X to the power of Y658659positional arguments:660  x              the base661  y              the exponent662663optional arguments:664  -h, --help     show this help message and exit665  -v, --verbose666  -q, --quiet667```668669## Заключение670671Модуль [`argparse`](https://python-all.ru/3.5/library/argparse.html#module-argparse) предлагает гораздо больше, чем показано здесь. Его документация весьма подробна и обстоятельна, полна примеров. Пройдя этот учебник, вы легко сможете её усвоить, не чувствуя перегрузки.672