argparse.md
1> **Источник:** https://python-all.ru/3.2/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.2/library/argparse.html#module-argparse), рекомендуемый модуль для разбора командной строки в стандартной библиотеке Python.1314> **Примечание**15>16> Существуют ещё два модуля, выполняющих ту же задачу, а именно [`getopt`](https://python-all.ru/3.2/library/getopt.html#module-getopt) (аналог `getopt()` из языка C) и устаревший [`optparse`](https://python-all.ru/3.2/library/optparse.html#module-optparse). Также обратите внимание, что [`argparse`](https://python-all.ru/3.2/library/argparse.html#module-argparse) основан на [`optparse`](https://python-all.ru/3.2/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.2/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.2/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.2/library/argparse.html#module-argparse) обрабатывает переданные ему опции как строки, если не указать иное. Итак, давайте укажем [`argparse`](https://python-all.ru/3.2/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.2/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"`. Это означает, что если опция указана, присваивается значение `True` переменной `args.verbose`. Отсутствие указания подразумевает `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- И, как и в случае с действием “store\_true”, если не указать флаг `-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.2/library/exceptions.html#TypeError)).507508И:509510```sh511$ python3 prog.py 451216513```514515Вы уже можете многое сделать, используя только то, что мы узнали, а мы лишь коснулись поверхности. Модуль [`argparse`](https://python-all.ru/3.2/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.2/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.2/library/argparse.html#module-argparse) предлагает гораздо больше, чем показано здесь. Его документация довольно подробна, доскональна и полна примеров. Пройдя это руководство, вы сможете легко её усвоить, не чувствуя себя перегруженным.672