Свой интерфейс командной строки с блэкджеком и Python

Свой интерфейс командной строки с блэкджеком и Python

Разбираемся, как это сделать. Библиотека argparse поможет принимать значение конфига в командной строке.

Вот вам четыре шага:

  1. Импортируйте библиотеку.
  2. Создайте парсер.
  3. Добавьте в него аргументы.
  4. Запустите .parse_args() .

Последний приведёт к объекту Namespace . Он содержит простое свойство для каждого входного аргумента из терминала.

Для подробного разбора этапов посмотрите программу myls.py . Она перечисляет файлы в текущей директории. Ниже – реализация без argparse :

Скрипт работает, но вывод отличается от встроенной команды.

Улучшите код с argparse :

Первое отличие – отсутствие условного оператора if , который проверял бы аргументы. Библиотека берёт эту функцию на себя.

Мы импортировали argparse , создали простой парсер с описанием программы и определили ожидаемые от пользователя аргументы. Последним делом запустили .parse_args() для разбора аргументов на входе и получения объекта Namespace , который содержит пользовательский ввод.

После запуска вы увидите, как всего четыре строчки меняют результат:

Отсутствует нужный аргумент пути, поэтому получим ошибку.

А также программа принимает флаг -h , как в примере ниже:

Приложение отвечает на -h выводом справки. И это не требует от нас никаких усилий!

Всего четыре строчки кода превратили переменную args в объект Namespace . Он содержит свойства для аргументов, которые юзер вводит в интерфейс командной строки.

Назовите программу

По умолчанию библиотека использует значение элемента sys.argv[0] для наименования программы, что соответствует названию скрипта. Укажите имя ключевым словом prog :

Оно будет отображаться в справке:

Теперь программа называется myls , а не myls.py .

Выводите настраиваемую справку в интерфейс командной строки

По умолчанию argparse создаёт помощь своего формата. Настройте её с помощью usage :

Во время выполнения токен %(prog)s автоматически заменяется именем программы:

И справка показывает другую строку использования, где опция -h сменилась универсальными токеном [options] .

Отображайте текст до и после аргументов справки

Используйте два ключевых слова для настройки текста до и после справки:

  1. description : описание до вывода помощи
  2. epilog : текст после

Посмотрим, как работает epilog :

Задайте символ префикса

По умолчанию, тире – начинает необязательные аргументы. Измените его с помощью ключевого слова prefix_chars :

Программа стала поддерживать другой префикс, а справка претерпела изменения:

Она отображается аргументом /h . Используйте это для разработки под Windows.

Символы префикса для файлов

Сохраняйте аргументы для сложных программ запуска в файле и загружайте из него. argparse выполняет эту работу из коробки.

Для теста напишите программу:

При создании парсера мы задействовали ключевое слово fromfile_prefix_chars .

Запуск без аргументов приведёт к ошибке:

Создайте args.txt с параметрами в каждой строке:

У вас есть специальный символ префикса для указания файла с аргументами. Откройте интерфейс командной строки и запустите предыдущую программу:

Видим: argparse считывает аргументы из файла args.txt .

Разрешайте и запрещайте сокращения

Следующая программа выводит указанное вами значение для аргумента –input :

Посмотрите, как argparse обрабатывает сокращения и вызывает программу несколько раз:

А что случится, если передать аргумент –i 42 ? Библиотека не сможет понять, передавать 42 аргументу –input или –id , и выведет сообщение об ошибке:

Не нравится эта функция? Хотите заставить пользователей вводить полные названия опций? Просто отключите эту возможность ключевым словом allow_abbrev со значением False на этапе создания парсера:

Запустите код, и вы увидите, что сокращения недоступны:

Ошибка сообщает, что пользователь не указал параметр –input потому, что программа не распознала сокращение –inp .

Задавайте имена флагов и аргументов

Вы можете добавить в интерфейс командной строки два типа аргументов:

  • позиционные
  • необязательные

Позиционными командами оперирует программа.

В предыдущем примере path – позиционный аргумент. Без него программа не работает. Они называются позиционными потому, что позиция определяет их функцию.

Рассмотрим cp из Linux:

Первый позиционный аргумент после cp – источник файла для копирования. Второй – место назначения копии.

Необязательные аргументы изменяют поведение команд во время выполнения. В примере с cp необязательный аргумент флаг -r заставляет команду копировать директории рекурсивно.

Два типа аргументов отличаются синтаксисом: необязательные начинаются с – или — .

Хотите добавить необязательный аргумент? Вызовите .add_argument() и назовите новый аргумент, начиная с – .

Запустите и проверьте опцию -l :

Теперь программа принимает, но не требует опцию -l .

Задайте действие для аргумента

При добавлении необязательного аргумента можно указать действие. Задайте способ хранения значения в объекте Namespace , который вы получите после выполнения .parse_args() .

Некоторые действия предопределены и доступны для использования:

  • store хранит входное значение в объекте Namespace (действие по умолчанию).
  • store_const содержит постоянное значение, когда указаны соответствующие необязательные аргументы.
  • store_true хранит логическое True , когда указан соответствующий необязательный аргумент, и False в других случаях.
  • store_false хранит логическое False , когда указан соответствующий необязательный аргумент, и True в других случаях.
  • append содержит список, добавляя значение каждый раз, когда опция указана.
  • append_const хранит список, добавляя постоянное значение.
  • count хранит int , равный количеству использования опции.
  • help выводит справку.
  • version показывает версию программы.

Рассмотрим вышеуказанные опции на следующем примере:

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

Видно, что без указаний аргументов, значения по умолчанию – None .

Действие store хранит передаваемое значение:

store_const хранит определённую константу, когда предоставлены аргументы. В тесте мы указали аргумент b , и значение args.b стало 42 :

Действие store_true хранит логическое True при наличии передаваемых аргументов и False в остальных случаях. Нужно противоположное поведение? Воспользуйтесь действием store_false :

Создавайте список всех переданных значений одним аргументом с помощью append :

append_const похоже на append , но добавляет одно постоянное значение:

count считает количество передач аргумента. Оно полезно в реализации уровня подробностей вывода программы. Можно определить уровень как -v – меньше подробностей, чем -vvv :

Действие version просто показывает версию программы:

Ещё одна возможность: создавайте собственные действия. Для этого наследуйте класс argparse.Action и реализуйте пару методов.

Следующий пример – настраиваемое действие store , которое выводит больше подробностей, чем стандартное:

Программа вывела линию прежде, чем задать значение 42 параметру -i .

Задавайте количество значений для опции

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

Нужен аргумент, который принимает три значения? Укажите 3 в качестве значения nargs во время добавления параметра в парсер:

Теперь программа принимает три значения для параметра –input :

А значение переменной args.input – это список с тремя значениями.

Ключевое слово nargs также принимает:

  • ? : одно необязательное значение;
  • * : гибкое количество значений, которые собираются в список;
  • + : похоже на * , но требует хотя бы одного значения;
  • argparse.REMAINDER : все значения, которые остаются в командной строке.

В следующей программе позиционный аргумент input принимает одно значение. Если оно отсутствует, программа использует значение ключевого слово default :

Выбирайте значение для аргумента input . В данном случае будет использовано default :

Чтобы принять несколько значений и собрать их в список, укажите * в качестве значения nargs :

Этот код позволяет задавать гибкое число значений для ожидаемого аргумента:

Если вам нужно принять переменное количество значений и убедиться, что указано хотя бы одно значение, используйте + в качестве значений nargs :

Запустите программу без позиционных аргументов, и увидите точное сообщение об ошибке:

Напоследок представьте, что вам нужно захватить и отправить в список все оставшиеся аргументы, которые были указаны в командной строке. Для этого присвойте значение argparse.REMAINDER ключевому слову nargs :

Посмотрите, что происходит: первое значение будет связано с первым параметром. Остальные – со вторым:

Оставшиеся значения собираются в список.

Установите значение по умолчанию в отсутствии аргумента

Вы уже знаете, что пользователь может не указывать необязательные аргументы в командной строке. Когда аргументы не указаны, соответствующее значение ставится в None .

Но вы можете определить значение по умолчанию для аргумента:

Запустите программу без опции -a , и вы получите:

Теперь опция -a имеет значение 42 , хотя вы не указывали это явно в командной строке.

Установите тип аргумента

По умолчанию все входные значения обрабатываются как строки. У вас есть возможность определять тип соответствующего свойства объекта Namespace , которое вы получаете после вызова .parse_args() . Воспользуйтесь ключевым словом type :

Указывая значение типа int для аргумента, вы говорите argparse , что свойство .a объекта Namespace должно быть int вместо string :

Теперь значение аргумента проверяется во время выполнения. Если значение не подходит, выводится чёткая ошибка:

Установите допустимые значения для определённого аргумента

Ещё одна интересная особенность библиотеки argparse в Python. Предоставьте список принимаемых значений на стадии добавления новой опции:

Хотите принимать числовые значения? Используйте range() для определения диапазона принимаемых значений:

Тогда значение, указанное вами в командной строке, автоматически сравнивается со списком допустимых значений:

Если его там нет, вы получите сообщение об ошибке.

Установите необходимость аргумента

Хотите заставить пользователя вводить необязательный аргумент? Используйте ключевое слово required :

Установите значение required в True , и пользователь должен будет указывать значение для этого аргумента:

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