argparse в Python: разбор аргументов командной строки
Как за пятнадцать минут превратить скрипт с sys.argv в утилиту с флагами, справкой и понятными ошибками. Разбираем argparse на рабочих примерах для Python 3.x.

Пока скрипт запускается как python backup.py без опций, разбирать аргументы не нужно. Как только появляется «а давай передадим путь», «а ещё флаг для тихого режима», «а хорошо бы по умолчанию три копии» — начинается ад из sys.argv[1] и проверок вручную. Модуль argparse из стандартной библиотеки Python снимает эту боль: он парсит флаги, приводит типы, ставит значения по умолчанию, генерирует справку по -h и сам выводит понятную ошибку при неверном вводе. Ничего ставить не нужно — argparse входит в стандартную поставку Python 3.x.
К концу материала у вас будет утилита, которая принимает позиционные и именованные аргументы, флаги-переключатели, значения из списка допустимых и подкоманды в стиле git commit / git push. На чтение и повторение уйдёт минут пятнадцать.
Что нужно до начала
- Python 3.x — проверьте командой
python --version(на некоторых системахpython3 --version). Всё ниже работает начиная с Python 3.2, примеры проверены на 3.11. - Текстовый редактор и терминал. IDE не обязательна.
- Никаких сторонних пакетов.
argparseуже установлен.
Минимальный пример: один позиционный аргумент
Позиционный аргумент — тот, что передают без имени, по порядку. Классика: путь к файлу.
# greet.py — Python 3.x
import argparse
parser = argparse.ArgumentParser(description="Приветствие по имени")
parser.add_argument("name", help="имя, которое нужно поприветствовать")
args = parser.parse_args()
print(f"Привет, {args.name}")
Запустите:
python greet.py МирВ терминале появится строка Привет, Мир. А если запустить без аргумента, argparse сам напечатает ошибку и код возврата будет ненулевым:
usage: greet.py [-h] name
greet.py: error: the following arguments are required: nameУже здесь виден смысл модуля: вы не писали ни строчки про проверку количества аргументов, а сообщение об ошибке и справка появились сами. Наберите python greet.py -h — увидите автоматически собранный текст справки с описанием из description и help.
Именованные аргументы и значения по умолчанию
Именованные передают с флагом: --count 3. Их порядок не важен, а без указания подставляется default. Обратите внимание на type=int — без него всё, что пришло из командной строки, будет строкой.
# repeat.py — Python 3.x
import argparse
parser = argparse.ArgumentParser(description="Повторить приветствие")
parser.add_argument("name", help="имя")
parser.add_argument(
"-c", "--count",
type=int,
default=1,
help="сколько раз повторить (по умолчанию 1)",
)
args = parser.parse_args()
for _ in range(args.count):
print(f"Привет, {args.name}")
Проверка:
python repeat.py Мир --count 3Три строки Привет, Мир. Короткая форма -c 3 работает так же. Если передать --count три, argparse сам сообщит: argument -c/--count: invalid int value: 'три'.
Всё, что приходит из командной строки, — строка. Если аргумент должен быть числом, датой или путём, укажитеtype. Иначеargs.countокажется строкой"3", иrange("3")уронит скрипт.
Флаги-переключатели: включено или нет
Флагу вроде --verbose значение не передают — важен сам факт наличия. Для этого есть action="store_true": если флаг указан, атрибут станет True, иначе False.
# flags.py — Python 3.x
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-v", "--verbose", action="store_true",
help="подробный вывод")
args = parser.parse_args()
if args.verbose:
print("Режим подробного вывода включён")
else:
print("Обычный режим")
Запуск python flags.py даст «Обычный режим», а python flags.py -v — «Режим подробного вывода включён».
Ограничение допустимых значений через choices
Когда аргумент может принимать только несколько вариантов — формат, уровень логирования, среда, — задайте choices. argparse отвергнет всё остальное с внятной ошибкой.
# export.py — Python 3.x
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--format", choices=["json", "csv", "xml"],
default="json", help="формат вывода")
args = parser.parse_args()
print(f"Экспортирую в {args.format}")
Команда python export.py --format yaml завершится ошибкой: argument --format: invalid choice: 'yaml' (choose from 'json', 'csv', 'xml'). Проверять допустимость вручную не нужно.
Несколько значений в одном аргументе: nargs
Иногда нужно принять список: несколько файлов, набор тегов. Параметр nargs управляет количеством значений. Самые ходовые варианты собраны в таблице.
| Значение nargs | Что означает | Что окажется в атрибуте |
|---|---|---|
"+" | одно или более значений | список, минимум один элемент |
"*" | ноль или более значений | список, может быть пустым |
"?" | ноль или одно значение | одно значение либо default |
число, например 2 | ровно столько значений | список фиксированной длины |
# collect.py — Python 3.x
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("files", nargs="+", help="один или несколько файлов")
args = parser.parse_args()
print("Обрабатываю:", args.files)
python collect.py a.txt b.txt c.txt выведет Обрабатываю: ['a.txt', 'b.txt', 'c.txt']. Без единого файла argparse потребует хотя бы один, потому что задан "+".
Подкоманды в стиле git: subparsers
Крупная утилита делится на команды: tool init, tool build, tool deploy. У каждой свои аргументы. Для этого есть add_subparsers.
# tool.py — Python 3.x
import argparse
parser = argparse.ArgumentParser(description="Мультикомандная утилита")
subparsers = parser.add_subparsers(dest="command", required=True)
# подкоманда init
p_init = subparsers.add_parser("init", help="создать проект")
p_init.add_argument("path", help="каталог проекта")
# подкоманда build
p_build = subparsers.add_parser("build", help="собрать проект")
p_build.add_argument("--release", action="store_true",
help="сборка релиза")
args = parser.parse_args()
if args.command == "init":
print(f"Создаю проект в {args.path}")
elif args.command == "build":
mode = "release" if args.release else "debug"
print(f"Собираю в режиме {mode}")
Атрибут dest="command" подскажет, какую подкоманду выбрал пользователь. Параметр required=True у add_subparsers заставляет указать хотя бы одну команду; он доступен начиная с Python 3.7. Проверьте: python tool.py build --release напечатает «Собираю в режиме release», а python tool.py init myapp — «Создаю проект в myapp». У каждой подкоманды своя справка: python tool.py build -h.
Если не получилось
- AttributeError: 'Namespace' object has no attribute 'count'. Имя атрибута берётся из длинного флага без дефисов:
--countстановитсяargs.count, а--dry-runпревращается вargs.dry_run(дефис меняется на подчёркивание). Проверьте, как назван аргумент. - Число сравнивается как строка, условие всегда ложно. Забыли
type=int. Без негоargs.count— строка"3", а не число. - error: unrecognized arguments. Передан флаг, который не объявлен через
add_argument, либо опечатка в имени флага. - error: the following arguments are required. Не передан обязательный позиционный аргумент. Позиционные обязательны по умолчанию; чтобы сделать необязательным, используйте
nargs="?"сdefault. - Скрипт молча падает на пустом вводе при subparsers. На Python до 3.7
requiredу subparsers не поддерживался, и без командыargs.commandоказывалсяNone. Проверьте версию или обрабатывайтеNoneвручную.
Что дальше
Каркас утилиты готов. Дальше стоит посмотреть в сторону нескольких вещей. Первое — type можно передать любую функцию, которая принимает строку и возвращает объект, включая собственную: так удобно валидировать пути или даты прямо на этапе разбора. Второе — argparse.FileType открывает файлы автоматически, но следите за тем, чтобы их закрывать. Третье — для сложных проектов с десятками команд посмотрите на сторонние библиотеки вроде Click или Typer, но начинать почти всегда стоит с argparse: он в стандартной библиотеке и не тянет зависимостей. Полный список параметров add_argument и всех значений action смотрите в официальной документации модуля — она подробная и с примерами.
Разбор научной статьи: Сложный текст — понятным языком, с терминами
Спросить за 12 ₽Источники: argparse — Parser for command-line options, arguments and sub-commands (Python docs), Argparse Tutorial (Python docs)
Частые вопросы
Чем argparse отличается от чтения sys.argv напрямую?
У меня Python 3.6, будут ли работать примеры?
Как сделать позиционный аргумент необязательным?
Почему мой флаг --dry-run недоступен как args.dry-run?
Нужно ли ставить argparse через pip?
Как передать несколько значений одному аргументу?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.