Как сделать консольную утилиту python

Обновлено: 04.07.2024

pdb — это встроенный отладчик для Python, который, в отличие от print() , позволяет отлаживать программу в процессе её работы.

Отладка Python-кода с помощью print

Как уже говорилось ранее, кто-то используют print() для отображения информации, которая помогает понять, что происходит в коде. Кто-то использует логи для тех же целей, но давайте не путать использование логов на продакшене и случаи, когда их используют во время поиска багов в коде и после удаляют.

Команды Python-отладчика

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

Sportmaster Lab , Санкт-Петербург, Москва, Липецк , От 100 000 до 150 000 ₽

Python есть встроенный отладчик под названием pdb. Это простая консольная утилита, которая обладает основной функциональностью для отладки кода. Но если вы ищете что-то более продвинутое, то стоит обратить внимание на ipdb – отладчик с функциональностью из IPython.

Проще всего вызвать отладчик pdb из кода, где вы работаете:

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

Эта команда покажет часть кода, на выполнении которой сейчас находится интерпретатор. Можно передать два аргумента first и last для просмотра определённого участка кода. Если указать только first, то будет выведен код вокруг искомой строки.

up(p) и down(d)

Эти команды используются для передвижения по стеку вызовов. С их помощью можно отследить, откуда была вызвана текущая функция.

step() и next()

Другая пара не менее важных команд. С их помощью можно выполнять код построчно. Единственное различие между ними в том, что next() перейдёт к следующей строке вне зависимости от вызываемых функций, а step() перейдёт в вызванную функцию, если это возможно.

break()

Эта команда позволяет создавать брейкпоинты без внесений изменений в код. Ниже разберём этот этап более детально.

Краткий список команд отладчика pdb:

  • args() — выводит аргументы функции;
  • continue() или (cont) — продолжит выполнение до первого брейкпоинта или до завершения программы;
  • help() — выводит список доступных команд или подсказки по определённой команде;
  • jump() — перепрыгивает к выполнению указанной строчки кода;
  • list() — выводит исходный код программы вокруг выбранной строки;
  • expression() — выводит значение выражения;
  • pp — выводит значение в «красивом» виде;
  • quit или exit() — отменяет выполнение программы;
  • return() — завершает выполнение текущей функции.

Продолжаем изучать Python-отладчик

Рассмотренный ранее способ работы с отладчиком требовал внесения изменения в код для вывода чего-нибудь или установки брейкпоинта. Но часто при работе с внешними библиотеками появляется необходимость в их отладке. Конечно, можно открыть исходный код библиотеки и вызвать pdb .

Но теперь есть возможность запускать приложение напрямую из отладчика без внесения изменения в код. Для этого воспользуемся следующей командой:

Как можно заметить, не нужно указывать полный путь до библиотеки. Можно указать относительную ссылку от sys.path . Таким же образом можно отлаживать и ваше приложение.

Теперь куда проще отлаживать код. Не надо вносить изменения в приложение или во внешние библиотеки.

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

В данном примере прерывание произойдёт только в случае, если json будет иметь в себе ключ time_entry .

Отладка кода Django

Если вы используете Django, то скорее всего знаете, что, если в настройках значение параметра DEBUG установлено как True , то для каждого исключения будет выводиться отдельная страница с указанием типа исключения, стек вызовов, локальные переменные и т.д.

Если вы хотите прокачать отладчик, то установите django-extensions и используйте команду runserver_plus для запуска сервера. Также можно указать пароль для доступа к отладке следующей командой:

Прим. перев. В Werkzeug, начиная с версии 0.11, появилась возможность доступа по паролю к отладчику. Это сделано для повышения безопасности при попытках несанкционированного доступа.

Если вы используете django-extensions, то получите страницу со всеми вызовами, кодом и окном отладчика.

Процесс отладки осуществляется с помощью WSGI библиотеки Werkzeug.

Существует множество способов отладки приложений, но специализированные инструменты могут дать вам огромное преимущество по сравнению с другими разработчиками и помогут сэкономить время и силы при поиске багов. Cреды разработки предлагают широкий выбор средств отладки, подробнее о них в нашей подборке лучших IDE и редакторов кода для Python.

Python — невероятно гибкий язык программирования, который хорошо интегрируется с существующими программами. Немало Python-кода написано в виде скриптов и интерфейсов командной строки (CLI).

Инструменты и интерфейсы командной строки — эффективная вещь, так как они позволяют автоматизировать практически всё что угодно. Как следствие, эти интерфейсы с течением времени могут стать довольно сложными.

Обычно всё начинается с простого скрипта на Python, который что-то делает. Например, получает доступ к веб-API и выводит результат в консоль:

Вы можете запустить этот скрипт с помощью команды python3 print_user_agent.py , и он выведет имя user-agent, использованного для вызова API.

27–28 ноября, Онлайн, Беcплатно

Как и было сказано, довольно простой скрипт.

Но что делать, когда подобная программа растёт и становится всё более сложной?

Решением этого вопроса мы сегодня и займёмся. Вы узнаете об основах написания интерфейсов командной строки на Python и о том, как click позволяет упростить этот процесс.

Используя эти знания, мы шаг за шагом перейдём от простого скрипта к интерфейсу командной строки с аргументами, опциями и полезными инструкциями по использованию. Всё это мы сделаем с помощью библиотеки click.

К концу этой статьи вы будете знать:

  • Почему click — лучшая альтернатива argparse и optparse;
  • Как с его помощью создать простой CLI;
  • Как добавить обязательные аргументы командной строки в ваши скрипты;
  • Как парсить флаги и опции командной строки;
  • Как сделать ваши консольные приложения более удобными, добавив справочный текст.

Вы увидите, как сделать всё это с минимальным количеством шаблонного кода.

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

Зачем вам писать скрипты и инструменты для командной строки на Python?

Код выше – всего лишь пример, не очень полезный в реальной жизни. На самом деле скрипты бывают куда более сложные. Возможно, вы имели опыт с ними и знаете, что они могут быть важной частью нашей повседневной работы: некоторые скрипты остаются на протяжении всего времени жизни проекта, для которого они были написаны. Некоторые начинают приносить пользу другим командам или проектам. У них даже может расширяться функционал.

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

Здесь приходят на выручку такие модули, как optparse и argparse, которые делают нашу жизнь на порядок проще. Но прежде чем мы с ними познакомимся, давайте разберёмся с терминологией.

Основы интерфейса командной строки

Интерфейс командной строки (CLI) начинается с имени исполняемого файла. Вы вводите имя в консоль и получаете доступ к главной точке входа скрипта, такого как pip.

В зависимости от сложности CLI обычно есть определённые параметры, которые вы можете передавать скрипту:

  1. Аргумент, который является обязательным параметром. Если его не передать, то CLI вернёт ошибку. Например, в следующей команде click является аргументом: pip install click .
  2. Опция – необязательный параметр, который объединяет имя и значение, например --cache-dir ./my-cache . Вы говорите CLI, что значение ./my-cache должно использоваться как директория для кэша.
  3. Флаг, который включает или выключает определённый сценарий. Вероятно, самым частым является --help . Вы только указываете имя, а CLI самостоятельно интерпретирует значение.

С более сложными CLI, такими как pip или Heroku CLI, вы получаете доступ к набору функций, которые собраны под главной точкой входа. Они обычно называются командами или подкомандами.

Возможно, вы уже использовали CLI, когда устанавливали Python-библиотеку с помощью команды pip install <имя пакета> . Команда install говорит CLI, что вы хотите использовать функцию установки пакета, и даёт вам доступ к параметрам, характерным для этой функции.

Пакеты для работы с командной строкой, доступные в стандартной библиотеке Python 3.x

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

Два наиболее известных пакета для этого — optparse и argparse. Они являются частью стандартной библиотеки Python и добавлены туда по принципу «всё включено».

По большей части они делают одно и то же и работают схожим образом. Главное отличие заключается в том, что optparse не используется начиная с Python 3.2, и argparse считается стандартом для создания CLI в Python.

Вы можете узнать о них больше в документации Python, но, чтобы иметь представление, как выглядит скрипт с argparse, посмотрите на пример ниже:

click против argparse: лучшая альтернатива?

Вероятно, вы смотрите на этот код и думаете: «Что это всё значит?» И это является одной из проблем argparse: код с ним неинтуитивен и сложночитаем.

Поэтому вам может понравиться click.

Click решает ту же проблему, что и optparse и argparse, но немного иначе. Он использует декораторы, поэтому ваши команды должны быть функциями, которые можно обернуть этими декораторами.

С click легко создавать многофункциональный CLI с небольшим количеством кода. И этот код будет легко читаться, даже когда ваш CLI вырастет и станет более сложным.

Пишем простой CLI на Python с помощью click

Вдоволь поговорив о CLI и библиотеках, давайте взглянем на пример, чтобы понять, как написать простой CLI с click. Как и в первом примере, мы создаём простой CLI, который выводит результат в консоль. Это несложно:

Не пугайтесь последних двух строк: это то, как Python запускает функцию main при исполнении файла как скрипта.

Более реалистичный пример CLI на Python с использованием click

Теперь, когда вы знаете, как click упрощает написание CLI, давайте взглянем на более реалистичный пример. Мы напишем программу, которая позволяет нам взаимодействовать с веб-API.

API, который мы дальше будем использовать, — OpenWeatherMap API. Он предоставляет информацию о текущей погоде, а также прогноз на пять дней для определённого местоположения. Мы начнём с тестового API, который возвращает текущую погоду для места.

Давайте посмотрим, что случится, когда мы обратимся к API с Лондоном в качестве местоположения:

Если вы смущены наличием API-ключа в примере сверху, не переживайте, это тестовый API-ключ, предоставляемый сервисом.

  • q — место, в котором мы хотим узнать погоду;
  • appid — наш API-ключ.

Это позволяет нам создать простую реализацию на Python с использованием библиотеки requests (опустим обработку ошибок и неудачных запросов для простоты):

Эта функция делает простой запрос к API, используя два параметра. В качестве обязательного аргумента она принимает location (местоположение), которое должно быть строкой. Также мы можем указать API-ключ, передавая параметр api_key при вызове функции. Это необязательно, так как по умолчанию используется тестовый ключ.

И вот мы видим текущую погоду в Python REPL:

Парсим обязательные параметры с click

Простая функция current_weather позволяет нам создать CLI с местоположением, указанным пользователем. Это должно работать примерно так:

Как вы, возможно, догадались, местоположение — это аргумент, поскольку оно является обязательным параметром для нашего погодного CLI.

Как нам сделать это при помощи click? Всё довольно просто, мы используем декоратор под названием argument . Кто бы мог подумать?

Давайте возьмём наш предыдущий пример и слегка изменим его, добавив аргумент location :

Если этот print выглядит для вас странно, не волнуйтесь — это новый способ форматирования строк в Python 3.6+, который называется f-форматированием.

Как вы видите, всё, что нам нужно сделать, это добавить дополнительный декоратор к нашей функции main и дать ему имя. Click использует имя в качестве имени аргумента, переданного обёрнутой функции.

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

В нашем случае значение аргумента командной строки location будет передано функции main в качестве аргумента location . Логично, не так ли?

Также вы можете использовать тире в именах, например api-key , которые click переведёт в snake case для имени аргумента в функции, например main(api_key) .

Реализация main просто использует нашу функцию current_weather для получения погоды в указанном месте. И затем мы с помощью print выводим полученную информацию.

Парсим опциональные параметры с click

Как вы, возможно, догадались, тестовый API ограничивает нас в возможностях. Поэтому, прежде чем мы продолжим, зарегистрируйтесь и получите настоящий API-ключ.

Первое, что нам нужно изменить, — URL, откуда берутся данные о текущей погоде. Это можно сделать, изменив значение переменной url в функции current_weather на URL, указанный в документации OpenWeatherMap:

Это изменение приведёт к неработоспособности нашего CLI, так как указанный API-ключ не работает с реальным API. Поэтому давайте добавим новый параметр в наш CLI, который позволит нам указывать API-ключ. Но сначала мы должны решить, будет ли этот параметр аргументом или опцией. Мы сделаем его опцией, так как добавление параметра вроде --api-key делает его более явным и говорящим за себя.
Мы хотим, чтобы наша программа запускалась таким образом:

Проще простого. Посмотрим, как добавить опцию к нашей существующей команде:

И снова мы добавляем декоратор к нашей функции main . В этот раз мы используем декоратор с говорящим именем @click.option и указываем имя для нашей опции, начинающееся с двух тире. Как вы видите, мы также можем указать сокращение для нашей опции с одним тире, чтобы сэкономить пользователю немного времени.

Как было сказано ранее, click создаёт аргумент для передачи в функцию main из длинного варианта имени. В случае с опцией он убирает впередистоящие тире и переводит её в snake case. Таким образом, --api-key становится api_key .

Чтобы всё заработало, осталось лишь передать API-ключ в функцию current_weather .

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

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

Можете себя похвалить, вы создали отличный небольшой CLI почти без шаблонного кода. Однако прежде чем вы решите отдохнуть, давайте убедимся, что новый пользователь будет знать, как пользоваться нашим CLI, путём добавления документации. Не бойтесь, всё будет просто.

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

Второе (и последнее), что мы сделаем, — добавим документацию для всей click-команды. Самый простой и самый питонический способ сделать это — добавить строку документации в нашу функцию main . Да, нам в любом случае нужно сделать это, поэтому это не лишняя работа:

Сложив всё вместе, мы получаем хороший вывод для нашего инструмента:

Подводим итоги

Итак, в этом уроке мы рассмотрели много всего. Можете гордиться собой, вы написали свой собственный CLI, и всё это с минимальным количеством шаблонного кода! Исходный код ниже доказывает это. Не стесняйтесь использовать его для собственных экспериментов:

Считается, что Python не лучший выбор для десктопных приложений. Однако, когда в 2016 году я собирался переходить от разработки сайтов к программному обеспечению, Google подсказал мне, что на Python можно создавать сложные современные приложения. Например blender3d, который написан на Python.

Скриншот программы Blender


Но люди, не по своей вине используют уродливые примеры графического интерфейса, которые выглядят слишком старыми, и не понравятся молодёжи. Я надеюсь изменить это мнение в своем туториале. Давайте начнём.

Мы будем использовать PyQt (произносится «Пай-Кьют‎»‎). Это фреймворк Qt, портированный с C++. Qt известен тем, что необходим C++ разработчикам. С помощью этого фреймворка сделаны blender3d, Tableau, Telegram, Anaconda Navigator, Ipython, Jupyter Notebook, VirtualBox, VLC и другие. Мы будем использовать его вместо удручающего Tkinter.

Требования

  1. Вы должны знать основы Python
  2. Вы должны знать, как устанавливать пакеты и библиотеки с помощью pip.
  3. У вас должен быть установлен Python.

Установка

Вам нужно установить только PyQt. Откройте терминал и введите команду:

Мы будем использовать PyQt версии 5.15. Дождитесь окончания установки, это займёт пару минут.

Hello, World!

Создайте папку с проектом, мы назовём его helloApp. Откройте файл main.py, лучше сделать это vscode, и введите следующий код:

Этот код вызывает QGuiApplication и QQmlApplicationEngine которые используют Qml вместо QtWidget в качестве UI слоя в Qt приложении. Затем, мы присоединяем UI функцию выхода к главной функции выхода приложения. Теперь они оба закроются одновременно, когда пользователь нажмёт выход. Затем, загружаем qml файл для Qml UI. Вызов app.exec(), запускает приложение, он находится внутри sys.exit, потому что возвращает код выхода, который передается в sys.exit.

Добавьте этот код в main.qml:

Этот код создает окно, делает его видимым, с указанными размерами и заголовком. Объект Text отображается в середине окна.

Revolut , Moscow, можно удалённо , По итогам собеседования

Теперь давайте запустим приложение:

Вы увидите такое окно:

Десктопное приложение на python

Обновление UI

Давайте немного обновим UI, добавим фоновое изображение и время:

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

Если сейчас запустить приложение, то текст появится в левом верхнем углу. Но нам нужен левый нижний угол, поэтому используем отступы:

После запуска вы увидите следующее:

Десктопное приложение на python

Показываем текущее время

Модуль gmtime позволяет использовать структуру со временем, а strftime даёт возможность преобразовать её в строку. Импортируем их:

Теперь мы можем получить строку с текущим временем:

Строка "%H:%M:%S" означает, что мы получим время в 24 часовом формате, с часами минутами и секундами (подробнее о strtime).

Давайте создадим property в qml файле, для хранения времени. Мы назовём его currTime.

Теперь заменим текст нашей переменной:

Теперь, передадим переменную curr_time из pyhton в qml:

Это один из способов передачи информации из Python в UI.

Запустите приложение и вы увидите текущее время.

Обновление времени

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

Чтобы использовать сигналы нам нужен подкласс QObject. Назовём его Backend.

У нас уже имеется свойства для строки со временем curr_time, теперь создадим свойство backend типа QtObject в файле main.qml.

Передадим данные из Python в qml:

В qml файле один объект QtObject может получать несколько функций (называемых сигналами) из Python.

Создадим тип Connections и укажем backend в его target. Теперь внутри этого типа может быть столько функций, сколько нам необходимо получить в backend.

Таким образом мы свяжем qml и сигналы из Python.

Мы используем потоки, для того чтобы обеспечить своевременное обновление UI. Создадим две функции, одну для управления потоками, а вторую для выполнения действий. Хорошая практика использовать в названии одной из функций _.

Создадим pyqtsignal и назовём его updated, затем вызовем его из функции updater.

Теперь нам осталось вызвать функцию updater. В нашем небольшом приложении, использовать отдельную функцию для вызова сигнала не обязательно. Но это рекомендуется делать в больших программах. Изменим задержку на одну десятую секунды.

Функция bootUp должна быть вызвана сразу же после загрузки UI:

Всё готово

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

Так должен выглядеть файл main.py:

Вот содержимое файла main.qml:

Сборка приложения

Для сборки десктопного приложения на Python нам понадобится pyinstaller.

Чтобы в сборку добавились все необходимые ресурсы, создадим файл spec:

Настройки файла spec

Параметр datas можно использовать для того, чтобы включить файл в приложение. Это список кортежей, каждый из которых обязательно должен иметь target path(откуда брать файлы) и destination path(где будет находится приложение). destination path должен быть относительным. Чтобы расположить все ресурсы в одной папке с exe-файлами используйте пустую строку.

Измените параметр datas, на путь к вашей папке с UI:

Параметр console установим в false, потому что у нас не консольное приложение.

Параметр name внутри вызова Exe, это имя исполняемого файла. name внутри вызова Collect, это имя папки в которой появится готовое приложение. Имена создаются на основании файла для которого мы создали spec — main.py.

Теперь можно запустить сборку:

В папке dist появится папка main. Для запуска программы достаточно запустить файл main.exe.

Так будет выглядеть содержимое папки с десктопным приложением на Python:

Содержимое папки с готовым приложением

О том, как использовать Qt Designer для создания UI приложений на Python читайте в нашей статье.

Python

Консольные приложения — это те, которые вы запускаете в терминале. Скорее всего, вы уже пытались их создать. Или, по крайней мере, думали об их создании.

Но создание консольного приложения — это одно, а публикация его в репозиторий с открытым кодом (например, PyPI) — совсем другое. Хотя ни первое, ни второе не является чем-то запредельно трудным.

В этой статье я подробно расскажу, как можно создать простой CLI на Python и опубликовать его в PyPI.

Начало

Не так давно я занялся изучением уязвимостей open-source кода и понял, что хочу иметь в арсенале инструмент командной строки, который мог бы находить уязвимости напрямую из терминала. Уязвимости open-source кода обычно публикуются в открытых базах данных. Их можно найти на таких сайтах, как CVE, NVD, WhiteSource Vuln и т.д.

В этой статье мы создадим примитивный скрейпер для поиска и просмотра уязвимостей с сайта CVE, обернем его в простое консольное приложение и опубликуем на PyPI.

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

Для создания виртуальной среды можно воспользоваться командой python -m venv <path/name> (для Python 3) либо установить virtualenvwrapper с помощью pip install virtualenvwrapper и создать виртуальную среду virtualenv через mkvirtualenv -p /path/topython <path/name> .

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

Как только все успешно запустилось, откройте свой проект в любом редакторе кода. Вы увидите похожую структуру:


Создание веб-скрейпера

Для того, чтобы искать и просматривать уязвимости на сайте CVE, потребуется веб-скрейпер. Он поможет нам собирать информацию об уязвимостях. Мы создаем скрейпер в Requests и BeautifulSoup. Вот что будет делать наш скрейпер:

1. искать уязвимости;

2. получать информацию об уязвимости по ее названию на CVE.

Теперь откроем папку cver и создадим в ней файл под названием cve_scraper . Затем пропишем его базовые настройки:

Поиск уязвимостей

Например, через URL можно получить список всех уязвимостей, связанных с Python:


Для извлечения данных открываем инструменты разработчика ( Developer Console ) и исследуем DOM-элемент с нужным представлением. Для этого кликните правой кнопкой по любому месту на странице и выберите “исследовать элемент” ( inspect element ) либо нажмите Ctrl + F12 .


Если вы присмотритесь к DOM-структуре выше, то увидите, что результаты представлены в виде таблицы, а каждое значение указано в отдельной строке под таблицей. Такие данные можно запросто извлечь:

1. отправляем запрос в SEARCH_URL с помощью Requests и получаем DOM-содержимое;

2. преобразуем DOM-содержимое в объекты BeautifulSoup . Это позволит нам выделять DOM-элементы с помощью CSS-селекторов, XPATH и других методов;

Просмотр информации об уязвимостях


Откройте инструменты разработчика и исследуйте DOM-структуру.


Такая структура чуть сложнее, поскольку в строках таблицы отсутствует ID или название класса. Поэтому нам нужно пройтись циклом по каждой строке и проверить, не является ли она подзаголовком. Если да, то следующий элемент берется в качестве содержимого-потомка. Каждый подзаголовок отображается в th , а его содержимое — в td .


Готово! Мы успешно создали веб-скрейпер с CVE. Теперь добавим в него две функции ( search и lookup_sve ), которые будут искать уязвимости и получать информацию по ним через CVE-ID .

Создание консольного приложения

Наш следующий шаг — структурирование и создание консольного приложения через библиотеку Click.

Click — это Python-пакет для создания красивых интерфейсов командной строки с минимальным количеством кода и возможностью компоновки. Это один из лучших Python-пакетов для создания CLI, и с ним очень удобно работать.

Click позволяет создавать интерфейсы командной строки любого уровня — от самых простых до навороченных (например, Heroku).

В нашем CLI мы реализуем две команды:

1. поиск уязвимости;

2. просмотр уязвимости.

В папке cver создаем файл под названием __main__.py и прописываем его базовые настройки:

Поиск уязвимостей

Здесь мы будем импортировать функцию поиска search из веб-скрейпера и передавать ей аргумент keyword из командной строки. Таким образом, приложение будет искать уязвимости, совпадающие с ключевым словом:

Для запуска этой команды:


Просмотр уязвимости

Принцип тот же: используем lookup_cve из веб-скрейпера и передаем туда аргумент name из команды look_up .

Для запуска этой команды:


Готово! Мы успешно создали инструмент командной строки по поиску с CVE.

Публикация консольного приложения на PyPI

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

PyPI — это хранилище приложений для пакетов Python. Там можно найти практически все пакеты, которые устанавливаются через pip . Для публикации пакета потребуется аккаунт на PyPI. Если он у вас уже есть, то смело читайте дальше.

Настройка пакета

Следующий шаг — это настройка Python-пакета с помощью setup.py . Если вы хотите, чтобы ваш пакет попал на PyPI, то нужно снабдить его базовым описанием. Эта информация указывается в файле setup.py .

Откройте setup.py в основной директории проекта и поместите в начало файла следующий код:

В примере выше мы преобразовали содержимое файла README.md в одну строку для дальнейшего использования. Кроме того, мы перечислили все необходимые модули из requirements.txt и сгенерировали ссылки на их зависимости.

Ваш файл requirements.txt выглядит примерно так:

Теперь давайте рассмотрим параметры настроек:

В коде выше мы добавили множество строк. Но подробнее обсудим только те из них, которые нужны для установки.

1. name — название пакета, которое появится на PyPI;

2. version — текущая версия пакета;

3. packages — пакеты и подпакеты с исходным кодом. В ходе установки мы пользуемся модулем find_packages . Он автоматически находит все подпакеты;

4. install_requires — используется для перечисления всех зависимостей или сторонних библиотек пакета. В cver мы пользуемся Requests, Beautifulsoup 4 и Click. Их нужно включить в требования к установке install_requires . Нам не нужно добавлять эту информацию вручную, поскольку она присутствует в requirements.txt ;

5. entry_points — используется для создания скриптов, которые вызывают функцию внутри пакета. В данном случае мы создаем новый скрипт cver , который вызывает main() внутри файла cver/__main__.py . Наш основной элемент — это __main__.py , который вызывает функцию main() для запуска Click.

До того, как опубликовать пакет на PyPI или выложить в открытый доступ, необходимо снабдить его документацией. То, как будет выглядеть документация, целиком и полностью зависит от самого проекта. Это может быть как простой файл README.md , так и Readme.rst .

Пример хорошо оформленного README.md :

Кроме того, не забудьте создать файл .gitignore :

Публикация на PyPI

Теперь ваш пакет готов к публикации на PyPI. Еще раз проверьте, есть ли у вас уже аккаунт на PyPI. Добавьте к нему тестовый аккаунт на тестовом сервере PyPI. Этот аккаунт нужен для тестирования пакетов перед публикацией их на рабочем сервере.

Загружать Python-пакеты на PyPI мы будем с помощью специального инструмента — Twine. По идее, вы уже установили его на одном из предыдущих этапов. Если нет, то это можно сделать через pip install twine .

Создание и локальное тестирование пакета на тестовом сервере

Python-пакеты, опубликованные на PyPI, не распространяются в виде «голого» кода. Они оборачиваются в дистрибутивы. Самыми распространенными форматами дистрибутивов в Python являются Wheels и Source Archives.

Wheels — это zip-архив с кодом и готовыми расширениями. Source Archives содержит исходный код и вспомогательные файлы, упакованные в tar-архив.

Для локального тестирования пакета выполните:

Теперь мы можем использовать его как:

Для проверки пакета на тестовом сервере PyPI нужно сгенерировать сборку для локального тестирования. При создании этой сборки сгенерируются архивы Wheels и Source Archives.

Код ниже сгенерирует два файла в директории dist :

Затем воспользуемся Twine. Теперь мы можем загрузить пакет на тестовый сервер PyPI:

Затем у вас спросят логин и пароль.


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

Для установки из TestPyPI выполните следующую команду:

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

Протестировав все команды локально, переходите к публикации пакета на рабочем сервере:

В процессе загрузки укажите свой логин и пароль. Вот и все!


Теперь пакет можно установить через:

Поздравляю! Ваш пакет был опубликован на PyPI. Просмотреть его можно здесь!

Заключение

В этой статье я пошагово объяснил процесс создания и публикации консольного приложения на Python.

Python

Все мы, специалисты по анализу данных, выполняем множество рутинных и повторяющихся действий. Сюда относятся: создание еженедельных отчетов, ETL-операции (извлечение, преобразование, загрузка), обучение моделей с помощью различных наборов данных и т.д. Зачастую на выходе у нас появляется множество Python -скриптов, и каждый раз при выполнении кода нам приходится менять его параметры. Лично меня это бесит! Именно поэтому я стал превращать скрипты в повторно используемые инструменты интерфейса командной строки ( CLI -инструменты). Это повысило эффективность и продуктивность моей каждодневной работы. Начинал я с Argparse , но не особо проникся им, поскольку приходилось писать множество убогого кода. И тут я подумал: неужели нельзя достичь тех же результатов без постоянного переписывания кода? Да и вообще, смогу ли я когда-нибудь получать удовольствие от создания CLI -инструментов?

Так что же такое Click ? Из официальной документации следует:

Click призван сделать процесс написания инструментов командной строки быстрым и увлекательным, избавляя при этом от всякого рода разочарований из-за невозможности реализации желаемого CLI API.

Звучит шикарно! Как считаете?

В данной статье я поделюсь с вами практическим руководством по пошаговому созданию Python CLI с помощью Click на Python и продемонстрирую вам базовые опции и преимущества этой библиотеки. Выполнив данный пример, вы научитесь писать CLI -инструменты быстро и безболезненно 🙂 Давайте уже займемся делом!

Обучающий урок

В ходе данного урока мы будем пошагово создавать CLI с помощью Click на Python . Я начну с самых основ и в каждом шаге буду рассказывать про концепцию, предлагаемую Click . Дополнительно мне понадобится Poetry для управления пакетами и зависимостями.

Подготовка

Для начала давайте установим Poetry . Существует множество способов установки, однако здесь мы воспользуемся pip :

Затем создадим в Poetry новый проект и назовем его cli-tutorial . Далее добавим зависимости click и funcy и создадим файл cli.py , который позже заполним кодом.

Я включил сюда funcy , поскольку он пригодится мне в дальнейшем. Ну а сейчас мы готовы к реализации своего первого CLI . Небольшое примечание: пример кода можно найти на GitHub.

Наш первый CLI на Click

Наш первоначальный CLI читает CSV -файл с диска, обрабатывает его (как именно он это делает — пока что не важно) и сохраняет результат в Excel . Пути к входному и выходному файлу настраиваются пользователем. И пользователь должен указать путь к входному файлу. Путь к выходному файлу указывается по желанию. Обычно им считается output.xlsx . Вот так выглядит этот код при использовании Click :

И что мы тут делаем?

2. Затем определяем аргументы командной строки через декоратор click.option . Но внимательно следите за правильными названиями аргументов в декорированной функции. Если в click.option добавляется строка без дефиса, то аргумент должен совпадать с этой строкой. Этим и объясняется --in и in_file . Если все имена начинаются с дефисов, то Click создает название аргумента по самому длинному имени и заменяет все дефисы внутри слова на нижнее подчеркивание. Название пишется в нижнем регистре. Пример: --out-file и out_file . Более подробно можно почитать в документации по Click .

3. Через соответствующие аргументы click.option задаем наши предварительные условия значениями по умолчанию или необходимыми аргументами.

4. Добавляем текст справки к нашим аргументами. Он будет показываться при вызове функции через --help . Здесь же отображается docstring из нашей функции.

Теперь можете вызвать этот CLI несколькими способами:

Круто! Вот мы и создали свой первый CLI с помощью Click !

Обратите внимание: я не прописываю read_csv , process_csv и write_excel , т.к. предполагаю, что они существуют и корректно выполняют свою работу.

Спецификация типов

В нашем примере с CLI мы хотели, чтобы пользователь передавал корректный путь к существующему файлу, для которого у нас есть разрешения на чтение. Если эти условия соблюдены, то мы загружаем входной файл. Кроме того, пользователь может задать путь к выходному файлу, и этот путь также должен быть действительным. Все это можно сделать, передав объект click.Path в аргумент type декоратора click.option .

click.Path — это один из нескольких готовых типов в Click . Помимо стандартных решений, вы можете создавать настраиваемые типы. Однако в данной статье эта тема не освещается. Почитать подробнее про пользовательские типы можно в документации.

Логические флаги

Еще одна полезная функция Click — это логические флаги. И, пожалуй, самым известным из них является флаг verbose . При значении true ваш инструмент выводит всю информацию в терминал. При значении false показываются только некоторые данные. В Click это можно реализовать следующим образом:

Все, что от вас требуется, — это добавить еще один декоратор click.option и установить is_flag=True . Теперь для получения подробного вывода нужно всего лишь вызвать CLI :

Переключатель функций

Здесь я добавил три декоратора click.option для трех возможных URL -адресов серверов. Важный момент: все три опции содержат одну общую переменную server_url . В зависимости от выбранной опции значение server_url соответствует значению, определенному в flag_value . Их вы выбираете, добавляя в качестве аргумента --dev , --test или --prod . Таким образом, при выполнении:

Запрос на ввод логина и пароля

К счастью или несчастью, наши сервера защищены паролями. Так что для загрузки файла на сервер потребуется имя пользователя и пароль. Конечно же, их можно задать стандартными аргументами click.option . Но тогда ваш пароль сохранится в виде обычного текста в истории команд, а это несет определенную угрозу для безопасности.

Поэтому мы предпочитаем выдавать пользователю запрос на ввод пароля, не передавая его в терминал и не сохраняя в истории команд. Что до логина, то здесь нам по душе простой запрос на ввод с передачей в терминал. А при определенных познаниях в Click ничего проще и не придумаешь. Вот наш код:

Чтобы добавить подсказку для ввода аргумента, установите prompt=True . Это действие добавит запрос везде, где пользователь не проставил аргумент --user , однако он может потребоваться. Если нажать на Enter в запросе, то проставится значение по умолчанию. Оно определяется с помощью другой полезной функции Click .

Запрос на ввод и подтверждение пароля без отправки его в терминал стало чем-то настолько обыденным, что Click придумал для этого специальный декоратор password_option . Важное примечание: пользователь все равно будет передавать пароль через --password MYSECRETPASSWORD . Однако так он сможет этого не делать.

Вот и все. Мы создали полноценный CLI . Перед тем, как подвести финальную черту, мне бы хотелось поделиться еще одной полезной подсказкой.

Poetry-скрипты

Последним штрихом этой статьи, который никак не связан с самим Click , но идеально вписывается в тему CLI , является создание Poetry -скриптов. Эти скрипты позволяют создавать исполняемые модули для вызова Python -функций из командной строки так же, как это делается в Setuptools -скриптах. Как это выглядит? Для начала добавим в файл pyproject.toml следующие строки:

Значение your-wanted-name — это псевдоним для функции process , определенной в модуле cli_tutorial.cli . Теперь вы можете вызвать ее следующим образом:

Таким образом, вы, например, сможете включать несколько CLI -функций в один файл, определять псевдонимы и не добавлять блок if __name__ == “__main__” .

Итог

В данной статье я показал вам, как пользоваться Click и Poetry для простого и эффективного создания CLI -инструментов. Это был лишь небольшой пример возможностей Click . В библиотеке есть и другие полезные функции, как, например, обратные вызовы, вложенные команды или предварительный выбор значений. Еще раз призываю всех заинтересовавшихся темой почитать документацию по Click .

Читайте также: