Последовательность параметров проходит через обработчик и разделяется на настройки
Программирование

Аргументы командной строки в Python: понятный argparse

Добавляем скрипту позиционные аргументы, именованные параметры и флаги, получаем автоматическую справку и проверяем ввод до запуска основной работы.

Содержание

Пока путь и режим записаны прямо в коде, для новой задачи приходится редактировать файл. Консольной программе удобнее передавать их при запуске: python report.py data/report.csv --limit 10 --verbose. Модуль argparse разбирает такую команду, проверяет значения и сам формирует справку.

Позиционный аргумент определяется местом в команде. Именованный параметр начинается с -- и получает значение после имени. Флаг меняет режим самим присутствием и обычно не требует следующего значения.

Пример продолжает работу с файлом из урока о JSON и CSV и использует объект Path, разобранный в материале о pathlib.

Сначала опишите интерфейс команды

Создайте рядом с учебными данными файл report_cli.py. Этот вариант только разбирает аргументы и печатает результат; файлы он пока не читает:

import argparse
from pathlib import Path


def build_parser():
    parser = argparse.ArgumentParser(
        description="Показывает строки CSV-отчёта"
    )
    parser.add_argument("report", type=Path, help="путь к CSV-файлу")
    parser.add_argument(
        "--limit",
        type=int,
        default=10,
        help="сколько строк показать (по умолчанию: 10)",
    )
    parser.add_argument(
        "--format",
        choices=("text", "json"),
        default="text",
        help="формат вывода",
    )
    parser.add_argument(
        "--verbose",
        action="store_true",
        help="показать дополнительные сведения",
    )
    return parser


def main(argv=None):
    parser = build_parser()
    args = parser.parse_args(argv)
    print(args)


if __name__ == "__main__":
    main()

Запустите python report_cli.py --help. В ответ появятся синтаксис команды, описание и список аргументов. type=Path превращает текст пути в объект, type=int проверяет целое число, choices ограничивает формат двумя значениями, а store_true возвращает True, только если указан флаг.

Команда python report_cli.py data/report.csv --limit 5 --verbose напечатает пространство имён с выбранными значениями. Пока программа не проверяет существование файла — тип Path отвечает лишь за представление пути.

Добавьте правила, которые нельзя выразить одним type

Нулевой или отрицательный лимит является целым числом, но не имеет смысла для отчёта. Добавьте проверку в main сразу после parse_args:

def main(argv=None):
    parser = build_parser()
    args = parser.parse_args(argv)

    if args.limit <= 0:
        parser.error("--limit должен быть больше нуля")
    if not args.report.is_file():
        parser.error(f"файл не найден: {args.report}")

    print(args)

Проверьте python report_cli.py missing.csv --limit 0. Программа завершится до основной работы, покажет краткий синтаксис и причину ошибки. Для ошибки командной строки argparse использует ненулевой код выхода; его может распознать shell-скрипт или планировщик.

Не превращайте type в функцию, которая удаляет файлы или обращается к сети. Разбор аргументов должен проверять ввод без необратимых побочных действий. Основная работа начинается только после успешной проверки всей команды.

Отделите разбор от обработки файла

Теперь добавьте импорт csv и функцию, которая только читает первые строки. Она возвращает данные, а не решает, как их отображать:

import csv


def load_rows(path, limit):
    rows = []
    with path.open("r", encoding="utf-8", newline="") as file:
        reader = csv.DictReader(file)
        for row in reader:
            rows.append(row)
            if len(rows) >= limit:
                break
    return rows

Замените последний print(args) в main вызовом функции и выводом результата:

    rows = load_rows(args.report, args.limit)

    if args.verbose:
        print(f"Прочитано строк: {len(rows)}")

    if args.format == "json":
        import json
        print(json.dumps(rows, ensure_ascii=False, indent=2))
    else:
        for row in rows:
            print(row)

Команда python report_cli.py data/report.csv --format json --limit 1 должна вывести JSON-массив с одной записью. Программа только читает входной файл и пишет результат в стандартный вывод; исходный CSV не меняется.

Импорт json лучше перенести в начало файла, когда формат станет постоянной частью программы. Здесь он оставлен рядом с единственным местом использования, чтобы показать связь выбранного режима и действия.

Справка является частью интерфейса

Хорошее значение help отвечает на вопрос, что передать, а не повторяет имя параметра. Укажите единицы измерения, допустимый формат пути и значение по умолчанию. Пример команды можно добавить в epilog, если сочетание аргументов трудно понять с первого взгляда.

Не используйте один флаг для двух разных смыслов. Если --force одновременно удаляет старый файл и игнорирует сетевую ошибку, пользователь не может оценить последствия. Для опасного действия нужны точное имя, предварительная проверка и понятный способ отмены.

Подготовьте функцию к автоматической проверке

Параметр argv=None позволяет обычному запуску читать sys.argv, а тесту — передать список вроде ["report.csv", "--limit", "2"]. Благодаря этому интерфейс команды можно проверять без изменения глобального состояния процесса.

Ошибки открытия CSV всё равно должны обрабатываться отдельно: файл может исчезнуть после проверки или оказаться недоступным. Понятные сообщения об исключениях рассмотрены в предыдущем уроке, а системный журнал работы будет добавлен в материале о logging.

Официальный учебник argparse и справочник модуля описывают остальные действия и варианты группировки параметров.

Рекламное местоВаша компания здесьРазместить рекламу

Самопроверка

Проверьте, что материал усвоен

Ответьте на все вопросы. Результат сохранится только в этом браузере и будет учтён в статистике прочитанных материалов.

01Как описать флаг, который включается самим присутствием в команде?
02Что даёт параметр choices?
03Где лучше размещать полезную работу программы?

Разбираем коротко

Частые вопросы

Чем позиционный аргумент отличается от параметра с --?

Позиционный аргумент определяется своим местом в команде и обычно обязателен. Именованный параметр имеет имя с дефисами, может быть необязательным и допускает значение по умолчанию.

Нужно ли вручную писать обработчик --help?

Нет. ArgumentParser добавляет справку автоматически на основе описаний программы и аргументов.

Почему main принимает argv=None?

При обычном запуске argparse читает системную командную строку, а тест может передать функции собственный список аргументов без запуска отдельного процесса.