Как сделать ваши программы модульными
Итак, вы прочитали несколько руководств по созданию CLI в python. Вы загрузили Click, создали несколько групп и теперь у вас есть рабочий интерфейс командной строки!
Затем вы начинаете думать о дополнительных командах и понимаете, что это не масштабируется. Добавление всего в один файл приводит к беспорядку, а мысль о том, что над ним работают несколько команд, вызывает мурашки по коже. В этой статье мы сосредоточимся на двух подходах к масштабированию вашего интерфейса командной строки, чтобы сделать его более модульным и простым в управлении. Включен репозиторий Github с первоначальным проектом и различными рефакторингами.
В этом руководстве предполагается, что вы понимаете, как работает Click, но если вы этого не понимаете, вы можете прочитать следующие три статьи, чтобы освоиться:
Наш интерфейс командной строки
Тестовый cli, который мы будем создавать, будет содержать три действия:
- Создайте
- Удалить
- получить
Каждое действие может быть выполнено на двух целях:
- файл
- каталог
Макет проекта V1
Чтобы создать нашу первую версию cli, мы следовали руководству и поместили все в один файл. Не лучшая практика… но это сработало! Наш проект выглядит так.
├── main.py ├── setup.py
Вы можете найти код в папке V1 репозитория github. Мы используем групповые декораторы для структурирования нашей иерархии, как показано ниже.
Это работает, и мы можем скомпилировать наш CLI, но добавление дополнительных функций становится более загроможденным, поэтому мы пытаемся реорганизовать код, чтобы сделать его более модульным.
V1.5 Пытаясь быть модульным
Мы рефакторим наш код и добавляем файлы file.py и directory.py. Мы копируем и вставляем в них наши функции с декораторами, но теперь сталкиваемся с проблемой, как нам структурировать импорт?
Мы пытаемся импортировать нашу группу CLI верхнего уровня в подмодули и таким образом добавлять команды, но получаем пустые подкоманды. Пришло время пересмотреть наши возможности.
Схема модульного проекта V2
Чтобы помочь создать более масштабируемый подход, мы собираемся добавить модули Python в наш каталог. Наш макет проекта будет отражать наши категории (существительные) с папкой верхнего уровня, содержащей точку входа cli, два модуля и установочный файл.
├── main.py ├── setup.py └── src ├── directories │ └── directory.py └── files └── file.py
Теперь у нас есть выбор того, как мы хотели бы, чтобы наши пользователи взаимодействовали с нашим cli, либо структурируя его так, чтобы команды шли сначала глаголом, либо существительным, то есть cli create file
или cli file create.
. В следующем разделе мы обсудим некоторые плюсы и минусы каждого из них. подход.
Структурирование ваших команд
В зависимости от того, с какими CLI вы работали, естественная иерархия для вашего cli может быть cli create file
или cli file create
. Первый называется иерархией глагол-существительное с клисом, таким как Powershell. Эти структуры хороши, когда команды имеют похожие действия, которые можно выполнить, и более точно отражают английский язык.
Второй тип существительного-глагола clis имеет больше примеров, включая AWS CLI и команды linux bash. В случае AWS каждая служба является второй частью каждой команды cli, такой как aws ec2 describe instances
и aws s3 ls.
.
Основное преимущество этой структуры cli заключается в том, что она позволяет командам вносить свой вклад в более крупный cli без изменения действий верхнего уровня, которые могут быть предприняты. Команды могут работать более автономно, а пользователи могут выбирать, какие подмодули загружать. Он также более точно следует хорошим принципам объектно-ориентированного программирования, не слишком полагаясь на общие методы в подклассах (группах), когда они не нужны.
Другие интерфейсы командной строки смешивают и сопоставляют структуру «существительное-глагол» и «глагол-существительное», например, kubectl с такими командами, как
kubectl config get-contexts
kubectl config view
А также такие команды, как
kubectl get pods
kubectl get services
Сегодня в следующем разделе мы расскажем, как выполнить обе настройки, и вам предлагается реализовать предпочтительный подход для вашего проекта.
Сначала имя существительное — Cli File Create
Сначала мы начнем с существительного, потому что это упрощает нашу настройку. В нашем main.py в папке Noun First вы заметите, как мы структурируем наш проект, мы импортируем каждую группу из наших подкаталогов и добавляем их как команду.
Это было довольно легко! Следует отметить, что я помещаю все в папку src, а затем в свой setup.py
импортирую все в src
как pymodule.
├── main.py
├── setup.py
└── src
├── каталоги
│ └── directory.py
└── файлы
└── file.py
Когда мы запустим cli, мы должны увидеть что-то вроде этого.
cli file Usage: cli file [OPTIONS] COMMAND [ARGS]... Options: --help Show this message and exit. Commands: create delete get
Глагол первый — Cli Создать файл
Наш второй подход заключается в том, чтобы наш глагол cli был первым, например cli create file
.
Этот подход немного сложнее, потому что мы не можем просто добавить команду create в нашу группу верхнего уровня cli, нам нужно их объединить. По этой причине мы можем написать вспомогательную функцию для команд слияния.
def merge_commands(group, command_collection:CommandCollection): """ Set the group's commands to those in the collection""" new_commands = {} command_sources = command_collection.sources for group in command_sources: for command_name,command in group.commands.items(): new_commands[command_name] = command group.commands = new_commands return group
Для каждой команды верхнего уровня мы создадим набор команд, а затем передадим нашу группу, чтобы переопределить ее пустые команды.
Всякий раз, когда мы хотим добавить новый модуль (существительное) для команды, мы можем добавить его в наш параметр sources в CommandCollection init, а наша программа позаботится обо всем остальном! Команда cli для создания будет выглядеть примерно так.
cli create Usage: cli create [OPTIONS] COMMAND [ARGS]... Options: --help Show this message and exit. Commands: directory Create directory file Create file
Примечание. Вам необходимо создать группы глаголов (создать, получить, удалить) в main.py и подмодулях!
Вывод
И вот оно. В этом руководстве мы узнали, как масштабировать наш Python Click cli, разбив наши группы на модули и поддерживая два типа структур cli. По мере дальнейшего масштабирования вы столкнетесь с более интересными проблемами, и мне было бы интересно узнать о них по ходу дела.