
Аргументы командной строки в 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 и справочник модуля описывают остальные действия и варианты группировки параметров.
Самопроверка
Проверьте, что материал усвоен
Ответьте на все вопросы. Результат сохранится только в этом браузере и будет учтён в статистике прочитанных материалов.
Разбираем коротко
Частые вопросы
Чем позиционный аргумент отличается от параметра с --?
Позиционный аргумент определяется своим местом в команде и обычно обязателен. Именованный параметр имеет имя с дефисами, может быть необязательным и допускает значение по умолчанию.
Нужно ли вручную писать обработчик --help?
Нет. ArgumentParser добавляет справку автоматически на основе описаний программы и аргументов.
Почему main принимает argv=None?
При обычном запуске argparse читает системную командную строку, а тест может передать функции собственный список аргументов без запуска отдельного процесса.


