Документация Python неофициальный перевод

argparse.md

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

1> **Источник:** https://python-all.ru/2.7/howto/argparse.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Руководство по Argparse89**автор**1011Tshepang Lekhonkhobe1213Это руководство предназначено для плавного введения в [`argparse`](https://python-all.ru/2.7/library/argparse.html#module-argparse), рекомендованный модуль разбора командной строки в стандартной библиотеке Python. Оно было написано для argparse в Python 3. Некоторые детали отличаются в 2.x, особенно некоторые сообщения об исключениях, которые были улучшены в 3.x.1415> **Примечание**16>17> Существуют ещё два модуля, выполняющие ту же задачу, а именно [`getopt`](https://python-all.ru/2.7/library/getopt.html#module-getopt) (аналог `getopt()` из языка C ) и устаревший [`optparse`](https://python-all.ru/2.7/library/optparse.html#module-optparse). Обратите также внимание, что [`argparse`](https://python-all.ru/2.7/library/argparse.html#module-argparse) основан на [`optparse`](https://python-all.ru/2.7/library/optparse.html#module-optparse), и поэтому очень похож по использованию.1819## Основные понятия2021Давайте покажем, какие возможности мы будем изучать в этом вводном руководстве, на примере команды **ls**:2223```sh24$ ls25cpython  devguide  prog.py  pypy  rm-unused-function.patch26$ ls pypy27ctypes_configure  demo  dotviewer  include  lib_pypy  lib-python ...28$ ls -l29total 2030drwxr-xr-x 19 wena wena 4096 Feb 18 18:51 cpython31drwxr-xr-x  4 wena wena 4096 Feb  8 12:04 devguide32-rwxr-xr-x  1 wena wena  535 Feb 19 00:05 prog.py33drwxr-xr-x 14 wena wena 4096 Feb  7 00:59 pypy34-rw-r--r--  1 wena wena  741 Feb 18 01:01 rm-unused-function.patch35$ ls --help36Usage: ls [OPTION]... [FILE]...37List information about the FILEs (the current directory by default).38Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.39...40```4142Из этих четырёх команд можно извлечь несколько понятий:4344- Команда **ls** полезна при запуске без каких-либо опций. По умолчанию она выводит содержимое текущего каталога.45- Если нужно больше, чем даётся по умолчанию, мы сообщаем программе дополнительные сведения. В данном случае мы хотим показать другой каталог – `pypy`. Мы указали так называемый позиционный аргумент. Он назван так потому, что программа понимает, что делать со значением, только по его позиции в командной строке. Это понятие лучше видно на примере команды **cp**, простейшее использование которой – `cp SRC DEST`. Первая позиция – *что нужно скопировать*, а вторая – *куда скопировать*.46- Теперь представим, что мы хотим изменить поведение программы. В нашем примере мы выводим больше информации о каждом файле, а не только имена. `-l` в этом случае называется необязательным аргументом.47- Это фрагмент справки. Она очень полезна: вы можете встретить незнакомую программу и понять, как она работает, просто прочитав её справку.4849## Основы5051Начнём с очень простого примера, который (почти) ничего не делает:5253```python54import argparse55parser = argparse.ArgumentParser()56parser.parse_args()57```5859Ниже приведён результат выполнения кода:6061```sh62$ python prog.py63$ python prog.py --help64usage: prog.py [-h]6566optional arguments:67  -h, --help  show this help message and exit68$ python prog.py --verbose69usage: prog.py [-h]70prog.py: error: unrecognized arguments: --verbose71$ python prog.py foo72usage: prog.py [-h]73prog.py: error: unrecognized arguments: foo74```7576Вот что происходит:7778- Запуск скрипта без опций не выводит ничего в stdout. Не очень полезно.79- Второй запуск начинает показывать полезность модуля [`argparse`](https://python-all.ru/2.7/library/argparse.html#module-argparse). Мы почти ничего не сделали, но уже получили хорошее сообщение справки.80- Опция `--help`, которую можно сократить до `-h`, – единственная опция, которую мы получаем бесплатно (т.е. её не нужно указывать). Всё остальное приводит к ошибке. Но даже в этом случае мы получаем полезное сообщение об использовании – тоже бесплатно.8182## Знакомство с позиционными аргументами8384Пример:8586```python87import argparse88parser = argparse.ArgumentParser()89parser.add_argument("echo")90args = parser.parse_args()91print args.echo92```9394И запуск кода:9596```sh97$ python prog.py98usage: prog.py [-h] echo99prog.py: error: the following arguments are required: echo100$ python prog.py --help101usage: prog.py [-h] echo102103positional arguments:104  echo105106optional arguments:107  -h, --help  show this help message and exit108$ python prog.py foo109foo110```111112Вот что происходит:113114- Мы добавили метод `add_argument()`, который используется для указания опций командной строки, которые программа готова принять. В данном случае я назвал его `echo`, чтобы оно соответствовало своей функции.115- Теперь для вызова программы требуется указать опцию.116- Метод `parse_args()` на самом деле возвращает некоторые данные из указанных опций, в данном случае `echo`.117- Переменная – это своего рода «магия», которую [`argparse`](https://python-all.ru/2.7/library/argparse.html#module-argparse) выполняет бесплатно (т.е. не нужно указывать, в какой переменной хранится это значение). Вы также заметите, что её имя совпадает со строковым аргументом, переданным методу – `echo`.118119Однако обратите внимание, что, хотя справка выглядит красиво, пока она не так полезна, как могла бы быть. Например, мы видим, что у нас есть позиционный аргумент `echo`, но не знаем, что он делает – только догадываемся или читаем исходный код. Давайте сделаем его немного полезнее:120121```python122import argparse123parser = argparse.ArgumentParser()124parser.add_argument("echo", help="echo the string you use here")125args = parser.parse_args()126print args.echo127```128129И получаем:130131```sh132$ python prog.py -h133usage: prog.py [-h] echo134135positional arguments:136  echo        echo the string you use here137138optional arguments:139  -h, --help  show this help message and exit140```141142А теперь давайте сделаем что-нибудь ещё более полезное:143144```python145import argparse146parser = argparse.ArgumentParser()147parser.add_argument("square", help="display a square of a given number")148args = parser.parse_args()149print args.square**2150```151152Ниже приведён результат выполнения кода:153154```sh155$ python prog.py 4156Traceback (most recent call last):157  File "prog.py", line 5, in <module>158    print args.square**2159TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'160```161162Всё пошло не так. Это потому, что [`argparse`](https://python-all.ru/2.7/library/argparse.html#module-argparse) воспринимает переданные ему параметры как строки, если не указать иное. Итак, укажем [`argparse`](https://python-all.ru/2.7/library/argparse.html#module-argparse) воспринимать ввод как целое число:163164```python165import argparse166parser = argparse.ArgumentParser()167parser.add_argument("square", help="display a square of a given number",168                    type=int)169args = parser.parse_args()170print args.square**2171```172173Ниже приведён результат выполнения кода:174175```sh176$ python prog.py 417716178$ python prog.py four179usage: prog.py [-h] square180prog.py: error: argument square: invalid int value: 'four'181```182183Всё прошло хорошо. Программа теперь даже корректно завершается при неверном вводе перед продолжением.184185## Знакомство с необязательными аргументами186187До сих пор мы работали с позиционными аргументами. Давайте посмотрим, как добавить необязательные.188189```python190import argparse191parser = argparse.ArgumentParser()192parser.add_argument("--verbosity", help="increase output verbosity")193args = parser.parse_args()194if args.verbosity:195    print "verbosity turned on"196```197198И вывод:199200```sh201$ python prog.py --verbosity 1202verbosity turned on203$ python prog.py204$ python prog.py --help205usage: prog.py [-h] [--verbosity VERBOSITY]206207optional arguments:208  -h, --help            show this help message and exit209  --verbosity VERBOSITY210                        increase output verbosity211$ python prog.py --verbosity212usage: prog.py [-h] [--verbosity VERBOSITY]213prog.py: error: argument --verbosity: expected one argument214```215216Вот что происходит:217218- Программа написана так, чтобы выводить что-то, когда указан `--verbosity`, и ничего не выводить, если не указан.219- Чтобы показать, что опция действительно необязательна, при запуске программы без неё ошибки не возникает. Обратите внимание: по умолчанию, если необязательный аргумент не указан, соответствующая переменная (в данном случае `args.verbosity`) получает значение `None`, из-за чего она не проходит проверку на истинность в операторе [`if`](https://python-all.ru/2.7/reference/compound_stmts.html#if).220- Справочное сообщение немного отличается.221- При использовании опции `--verbosity` необходимо также указать некоторое значение, любое значение.222223В приведённом выше примере `--verbosity` принимает любые целые числа, но для нашей простой программы на самом деле полезны только два значения: `True` или `False`. Давайте соответствующим образом изменим код:224225```python226import argparse227parser = argparse.ArgumentParser()228parser.add_argument("--verbose", help="increase output verbosity",229                    action="store_true")230args = parser.parse_args()231if args.verbose:232   print "verbosity turned on"233```234235И вывод:236237```sh238$ python prog.py --verbose239verbosity turned on240$ python prog.py --verbose 1241usage: prog.py [-h] [--verbose]242prog.py: error: unrecognized arguments: 1243$ python prog.py --help244usage: prog.py [-h] [--verbose]245246optional arguments:247  -h, --help  show this help message and exit248  --verbose   increase output verbosity249```250251Вот что происходит:252253- Теперь опция больше напоминает флаг, нежели что-то, требующее значения. Мы даже изменили имя опции в соответствии с этой идеей. Обратите внимание: теперь мы указываем новый ключевой аргумент `action` и присваиваем ему значение `"store_true"`. Это означает, что если опция указана, то `args.verbose` присваивается значение `True`. Если не указана – то `False`.254- Программа выдаёт ошибку, если указано значение, в полном соответствии с тем, что такое флаги на самом деле.255- Обратите внимание на другой текст справки.256257### Короткие опции258259Если вы знакомы с работой из командной строки, то заметили, что я ещё не касался темы коротких версий опций. Всё довольно просто:260261```python262import argparse263parser = argparse.ArgumentParser()264parser.add_argument("-v", "--verbose", help="increase output verbosity",265                    action="store_true")266args = parser.parse_args()267if args.verbose:268    print "verbosity turned on"269```270271И вот:272273```sh274$ python prog.py -v275verbosity turned on276$ python prog.py --help277usage: prog.py [-h] [-v]278279optional arguments:280  -h, --help     show this help message and exit281  -v, --verbose  increase output verbosity282```283284Обратите внимание, что новая возможность также отражена в справочном тексте.285286## Сочетание позиционных и необязательных аргументов287288Наша программа становится всё сложнее:289290```python291import argparse292parser = argparse.ArgumentParser()293parser.add_argument("square", type=int,294                    help="display a square of a given number")295parser.add_argument("-v", "--verbose", action="store_true",296                    help="increase output verbosity")297args = parser.parse_args()298answer = args.square**2299if args.verbose:300    print "the square of {} equals {}".format(args.square, answer)301else:302    print answer303```304305А теперь вывод:306307```sh308$ python prog.py309usage: prog.py [-h] [-v] square310prog.py: error: the following arguments are required: square311$ python prog.py 431216313$ python prog.py 4 --verbose314the square of 4 equals 16315$ python prog.py --verbose 4316the square of 4 equals 16317```318319- Мы вернули позиционный аргумент, отсюда и жалоба.320- Обратите внимание: порядок не важен.321322А что, если вернуть нашей программе возможность иметь несколько значений уровня подробности вывода и на самом деле их использовать:323324```python325import argparse326parser = argparse.ArgumentParser()327parser.add_argument("square", type=int,328                    help="display a square of a given number")329parser.add_argument("-v", "--verbosity", type=int,330                    help="increase output verbosity")331args = parser.parse_args()332answer = args.square**2333if args.verbosity == 2:334    print "the square of {} equals {}".format(args.square, answer)335elif args.verbosity == 1:336    print "{}^2 == {}".format(args.square, answer)337else:338    print answer339```340341И вывод:342343```sh344$ python prog.py 434516346$ python prog.py 4 -v347usage: prog.py [-h] [-v VERBOSITY] square348prog.py: error: argument -v/--verbosity: expected one argument349$ python prog.py 4 -v 13504^2 == 16351$ python prog.py 4 -v 2352the square of 4 equals 16353$ python prog.py 4 -v 335416355```356357Все они выглядят хорошо, кроме последнего, который выявляет ошибку в нашей программе. Давайте исправим её, ограничив значения, которые может принимать опция `--verbosity`:358359```python360import argparse361parser = argparse.ArgumentParser()362parser.add_argument("square", type=int,363                    help="display a square of a given number")364parser.add_argument("-v", "--verbosity", type=int, choices=[0, 1, 2],365                    help="increase output verbosity")366args = parser.parse_args()367answer = args.square**2368if args.verbosity == 2:369    print "the square of {} equals {}".format(args.square, answer)370elif args.verbosity == 1:371    print "{}^2 == {}".format(args.square, answer)372else:373    print answer374```375376И вывод:377378```sh379$ python prog.py 4 -v 3380usage: prog.py [-h] [-v {0,1,2}] square381prog.py: error: argument -v/--verbosity: invalid choice: 3 (choose from 0, 1, 2)382$ python prog.py 4 -h383usage: prog.py [-h] [-v {0,1,2}] square384385positional arguments:386  square                display a square of a given number387388optional arguments:389  -h, --help            show this help message and exit390  -v {0,1,2}, --verbosity {0,1,2}391                        increase output verbosity392```393394Обратите внимание: изменение также отражается как в сообщении об ошибке, так и в строке справки.395396Теперь давайте применим другой подход к работе с подробностью вывода, который довольно распространён. Он также соответствует тому, как исполняемый файл CPython обрабатывает собственный аргумент подробности (проверьте вывод `python --help`):397398```python399import argparse400parser = argparse.ArgumentParser()401parser.add_argument("square", type=int,402                    help="display the square of a given number")403parser.add_argument("-v", "--verbosity", action="count",404                    help="increase output verbosity")405args = parser.parse_args()406answer = args.square**2407if args.verbosity == 2:408    print "the square of {} equals {}".format(args.square, answer)409elif args.verbosity == 1:410    print "{}^2 == {}".format(args.square, answer)411else:412    print answer413```414415Введено ещё одно действие – “count”, для подсчёта количества вхождений определённых необязательных аргументов:416417```sh418$ python prog.py 441916420$ python prog.py 4 -v4214^2 == 16422$ python prog.py 4 -vv423the square of 4 equals 16424$ python prog.py 4 --verbosity --verbosity425the square of 4 equals 16426$ python prog.py 4 -v 1427usage: prog.py [-h] [-v] square428prog.py: error: unrecognized arguments: 1429$ python prog.py 4 -h430usage: prog.py [-h] [-v] square431432positional arguments:433  square           display a square of a given number434435optional arguments:436  -h, --help       show this help message and exit437  -v, --verbosity  increase output verbosity438$ python prog.py 4 -vvv43916440```441442- Да, теперь это больше похоже на флаг (аналогично `action="store_true"` в предыдущей версии нашего скрипта). Этим и объясняется жалоба.443- Кроме того, оно ведёт себя аналогично действию «store\_true».444- А вот демонстрация того, что даёт действие «count». Вы, вероятно, уже встречали подобное использование.445- И, как и в случае с действием “store\_true”, если не указать флаг `-v`, считается, что этот флаг имеет значение `None`.446- Как и следовало ожидать, при указании длинной формы флага мы получим тот же результат.447- К сожалению, наш вывод справки не очень информативен о новых возможностях скрипта, но это всегда можно исправить, улучшив документацию (например, через именованный аргумент `help`).448- Последний вывод обнаруживает ошибку в нашей программе.449450Исправим:451452```python453import argparse454parser = argparse.ArgumentParser()455parser.add_argument("square", type=int,456                    help="display a square of a given number")457parser.add_argument("-v", "--verbosity", action="count",458                    help="increase output verbosity")459args = parser.parse_args()460answer = args.square**2461462# исправление ошибки: заменить == на >=463if args.verbosity >= 2:464    print "the square of {} equals {}".format(args.square, answer)465elif args.verbosity >= 1:466    print "{}^2 == {}".format(args.square, answer)467else:468    print answer469```470471И вот что получается:472473```sh474$ python prog.py 4 -vvv475the square of 4 equals 16476$ python prog.py 4 -vvvv477the square of 4 equals 16478$ python prog.py 4479Traceback (most recent call last):480  File "prog.py", line 11, in <module>481    if args.verbosity >= 2:482TypeError: unorderable types: NoneType() >= int()483```484485- Первый вывод прошёл хорошо и исправляет предыдущую ошибку. То есть мы хотим, чтобы любое значение \>= 2 давало максимально подробный вывод.486- Третий вывод уже не так хорош.487488Исправим и эту ошибку:489490```python491import argparse492parser = argparse.ArgumentParser()493parser.add_argument("square", type=int,494                    help="display a square of a given number")495parser.add_argument("-v", "--verbosity", action="count", default=0,496                    help="increase output verbosity")497args = parser.parse_args()498answer = args.square**2499if args.verbosity >= 2:500    print "the square of {} equals {}".format(args.square, answer)501elif args.verbosity >= 1:502    print "{}^2 == {}".format(args.square, answer)503else:504    print answer505```506507Мы только что ввели ещё один именованный аргумент – `default`. Мы установили его в `0`, чтобы можно было сравнивать с другими целочисленными значениями. Помните: по умолчанию, если необязательный аргумент не указан, он получает значение `None`, и такое значение нельзя сравнить с целым числом (отсюда исключение [`TypeError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.TypeError)).508509И:510511```sh512$ python prog.py 451316514```515516Уже с тем, что мы узнали, можно уйти довольно далеко, а мы только коснулись поверхности. Модуль [`argparse`](https://python-all.ru/2.7/library/argparse.html#module-argparse) очень мощный, и мы рассмотрим его чуть подробнее, прежде чем завершить этот учебник.517518## Немного более продвинутый материал519520Что, если бы мы захотели расширить нашу крошечную программу, чтобы она вычисляла не только квадраты, но и другие степени:521522```python523import argparse524parser = argparse.ArgumentParser()525parser.add_argument("x", type=int, help="the base")526parser.add_argument("y", type=int, help="the exponent")527parser.add_argument("-v", "--verbosity", action="count", default=0)528args = parser.parse_args()529answer = args.x**args.y530if args.verbosity >= 2:531    print "{} to the power {} equals {}".format(args.x, args.y, answer)532elif args.verbosity >= 1:533    print "{}^{} == {}".format(args.x, args.y, answer)534else:535    print answer536```537538Вывод:539540```sh541$ python prog.py542usage: prog.py [-h] [-v] x y543prog.py: error: the following arguments are required: x, y544$ python prog.py -h545usage: prog.py [-h] [-v] x y546547positional arguments:548  x                the base549  y                the exponent550551optional arguments:552  -h, --help       show this help message and exit553  -v, --verbosity554$ python prog.py 4 2 -v5554^2 == 16556```557558Обратите внимание: до сих пор мы использовали уровень подробности, чтобы *изменять* выводимый текст. В следующем примере уровень подробности используется, чтобы выводить *больше* текста:559560```python561import argparse562parser = argparse.ArgumentParser()563parser.add_argument("x", type=int, help="the base")564parser.add_argument("y", type=int, help="the exponent")565parser.add_argument("-v", "--verbosity", action="count", default=0)566args = parser.parse_args()567answer = args.x**args.y568if args.verbosity >= 2:569    print "Running '{}'".format(__file__)570if args.verbosity >= 1:571    print "{}^{} ==".format(args.x, args.y),572print answer573```574575Вывод:576577```sh578$ python prog.py 4 257916580$ python prog.py 4 2 -v5814^2 == 16582$ python prog.py 4 2 -vv583Running 'prog.py'5844^2 == 16585```586587### Конфликтующие опции588589До сих пор мы работали с двумя методами экземпляра [`argparse.ArgumentParser`](https://python-all.ru/2.7/library/argparse.html#argparse.ArgumentParser). Познакомимся с третьим – `add_mutually_exclusive_group()`. Он позволяет указывать опции, которые противоречат друг другу. Давайте также изменим остальную часть программы, чтобы новая функциональность стала более осмысленной: мы введём опцию `--quiet`, которая будет противоположностью опции `--verbose`:590591```python592import argparse593594parser = argparse.ArgumentParser()595group = parser.add_mutually_exclusive_group()596group.add_argument("-v", "--verbose", action="store_true")597group.add_argument("-q", "--quiet", action="store_true")598parser.add_argument("x", type=int, help="the base")599parser.add_argument("y", type=int, help="the exponent")600args = parser.parse_args()601answer = args.x**args.y602603if args.quiet:604    print answer605elif args.verbose:606    print "{} to the power {} equals {}".format(args.x, args.y, answer)607else:608    print "{}^{} == {}".format(args.x, args.y, answer)609```610611Наша программа теперь проще, и ради демонстрации мы потеряли часть функциональности. В любом случае, вот вывод:612613```sh614$ python prog.py 4 26154^2 == 16616$ python prog.py 4 2 -q61716618$ python prog.py 4 2 -v6194 to the power 2 equals 16620$ python prog.py 4 2 -vq621usage: prog.py [-h] [-v | -q] x y622prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose623$ python prog.py 4 2 -v --quiet624usage: prog.py [-h] [-v | -q] x y625prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose626```627628Это должно быть легко понять. Я добавил последний вывод, чтобы вы могли увидеть, какую гибкость это даёт: например, смешивание длинной и короткой форм опций.629630Прежде чем закончить, вы, вероятно, захотите сообщить пользователям основное назначение вашей программы, на случай если они не знают:631632```python633import argparse634635parser = argparse.ArgumentParser(description="calculate X to the power of Y")636group = parser.add_mutually_exclusive_group()637group.add_argument("-v", "--verbose", action="store_true")638group.add_argument("-q", "--quiet", action="store_true")639parser.add_argument("x", type=int, help="the base")640parser.add_argument("y", type=int, help="the exponent")641args = parser.parse_args()642answer = args.x**args.y643644if args.quiet:645    print answer646elif args.verbose:647    print "{} to the power {} equals {}".format(args.x, args.y, answer)648else:649    print "{}^{} == {}".format(args.x, args.y, answer)650```651652Обратите внимание на небольшое различие в тексте использования. Обратите внимание на `[-v | -q]`, который сообщает, что мы можем использовать либо `-v`, либо `-q`, но не оба одновременно:653654```sh655$ python prog.py --help656usage: prog.py [-h] [-v | -q] x y657658calculate X to the power of Y659660positional arguments:661  x              the base662  y              the exponent663664optional arguments:665  -h, --help     show this help message and exit666  -v, --verbose667  -q, --quiet668```669670## Заключение671672Модуль [`argparse`](https://python-all.ru/2.7/library/argparse.html#module-argparse) предлагает гораздо больше, чем показано здесь. Его документация весьма подробна и обстоятельна, полна примеров. Пройдя этот учебник, вы легко сможете её усвоить, не чувствуя перегрузки.673