


Модуль argparse разбирает аргументы командной строки, формирует справку и сообщает об ошибках ввода. Описание интерфейса лучше отделить от основной функции программы: тогда одни и те же правила можно проверить на списке аргументов без запуска отдельного процесса.
В примере Mentoring.digital сделаем безопасный интерфейс утилиты отчётов. Она только показывает разобранные параметры. Создание файлов и обработку отчётов добавляют отдельно.
Сохраните код в report_cli.py. Пример подходит для Python 3.10 и новее. Позиционный аргумент задаёт тему, --limit принимает положительное целое число, --format ограничен двумя вариантами, --verbose работает как переключатель.
import argparse
def positive_int(value):
try:
number = int(value)
except ValueError:
raise argparse.ArgumentTypeError("нужно целое число")
if number <= 0:
raise argparse.ArgumentTypeError("число должно быть больше нуля")
return number
def build_parser():
parser = argparse.ArgumentParser(
description="Параметры учебного отчёта",
allow_abbrev=False,
)
parser.add_argument("topic", help="тема отчёта")
parser.add_argument("--limit", type=positive_int, default=10,
help="число строк, по умолчанию 10")
parser.add_argument("--format", choices=("text", "json"),
default="text")
parser.add_argument("--verbose", action="store_true")
return parser
def main(argv=None):
args = build_parser().parse_args(argv)
print(vars(args))
if __name__ == "__main__":
main()
allow_abbrev=False запрещает сокращённые длинные опции. Это делает интерфейс предсказуемее при добавлении новых флагов: пользователь передаёт --limit, а не случайно подходящее --li. Справка -h и --help создаётся автоматически.
python report_cli.py "Продажи за месяц" --limit 3 --format json --verbose
python report_cli.py --help
python report_cli.py test --limit 0
python report_cli.py test --format xml
В первом запуске topic будет строкой, limit целым числом 3, format строкой json, verbose значением True. Кавычки сохраняют тему с пробелами как один аргумент. В двух последних командах parser должен завершиться с сообщением об ошибке, не переходя к полезной работе.
Не используйте type=bool для флага. Строка «False» непустая, поэтому bool('False') даёт True. Для переключателя без значения подходит store_true. Если интерфейс требует пару --feature и --no-feature, отдельно рассмотрите BooleanOptionalAction.
parser = build_parser()
args = parser.parse_args(["test", "--limit", "2"])
assert args.limit == 2
assert args.verbose is False
try:
parser.parse_args(["test", "--limit", "-1"])
except SystemExit as error:
assert error.code == 2
else:
raise AssertionError("Отрицательное значение принято")
Здесь SystemExit перехватывается для проверки поведения в тесте. В обычной утилите не нужно гасить все исключения и продолжать работу с некорректными параметрами. Дополнительно проверьте отсутствие topic, неизвестный флаг, нечисловой limit и регистр значения JSON: choices в этом примере чувствителен к регистру.
Успешный parse_args не доказывает существование файла, доступность сервера или право на запись. Такие проверки выполняются на соответствующем шаге программы. Не передавайте введённые строки в оболочку через склеенную команду. Не помещайте пароли в аргументы: они могут попасть в историю команд и список процессов.
Разработку небольших утилит можно разобрать на занятиях по Python. Для проверки интерфейса своего скрипта выберите ментора по Python и принесите примеры корректных и ошибочных запусков.