Как сделать свой формат файла python
Для разработки расширений можно использовать язык программирования Python. По сравнению с классическими расширениями, написанными на C++, их легче разрабатывать, понимать, поддерживать и распространять в силу динамической природы самого Python.
Расширения на Python перечисляются в Менеджере модулей QGIS наравне с расширениями на C++. Поиск расширений выполняется в следующих каталогах:
В Windows домашний каталог (обозначенный выше как
) обычно выглядит как C:\Documents and Settings\(user) . Вложенные каталоги в этих папках рассматриваются как пакеты Python, которые можно загружать в QGIS как расширения.
Идея: Прежде всего нужна идея для нового расширения QGIS. Зачем это нужно? Какую задачу необходимо решить? Может, есть готовое расширения для решения этой задачи?
Создание файлов: Подробнее этот шаг описан ниже. Точка входа ( __init.py__ ). Тело расширения ( plugin.py ). Форма QT-Designer ( form.ui ), со своим resources.qrc .
Реализация: Пишем код в plugin.py
Тестирование: Закройте и снова откройте QGIS, загрузите своё расширение. Проверьте, что всё работает как надо.
Разработка расширения¶
Создание необходимых файлов¶
Ниже показано содержимое каталога нашего демонстрационного расширения:
Для чего используются файлы:
__init__.py = Точка входа расширения. Содержит общую информацию, версию расширения, его название и основной класс.
plugin.py = Основной код расширения. Содержит информацию обо всех действиях, доступных в расширении, а также основной код.
resources.qrc = XML-документ, созданный QT-Designer. Здесь хранятся относительные пути к ресурсам форм.
resources.py = Понятная Python версия вышеописанного файла.
form.ui = Интерфейс пользователя (GUI), созданный в QT-Designer.
form.py = Конвертированная в код Python версия вышеописанного файла.
metadata.txt = требуется в QGIS >= 1.8.0. Содержит общую информацию, версию расширения, его название и другие метаданые, используемые новым репозиторием расширений. Метаданным в metadata.txt отдается предпочтение перед методами из файла __init__.py . Если текстовый файл присутствует, именно он будет использоваться для получения этой информации. Начиная с QGIS 2.0 метаданные из __init__.py больше не будут использоваться и файл metadata.txt станет обязательным.
Здесь и вот здесь можно найти два способа автоматической генерации базовых файлов (скелета) типового Python расширения для QGIS. Кроме того, существует модуль Plugin Builder , который создает шаблон модуля прямо из QGIS и не требует соединения с Интернет. Это упростит работу и поможет быстрее начать разработку типового расширения.
Написание кода¶
__init__.py¶
Прежде всего, Менеджер модулей должен получить основные сведения о расширении, такие как его название, описание и т.д. Файл __init__.py именно то место, где должна быть эта информация:
metadata.txt¶
plugin.py¶
Если используется QGIS 1.9.90 или старше и необходимо разместить модуль в одном из новых меню ( Растр , Вектор , База данных или Web ), нужно модифицировать код функций initGui() и unload() . Так как эти новые пункты меню доступны только в QGIS 1.9.90, прежде всего необходимо проверить, что используемая версия QGIS имеет все необходимые функции. Если новые пункты меню доступны, мы можем разместить модуль в нужном месте, в противном случае будем использовать меню Модули как и раньше. Вот пример для меню Растр :
Полный список методов, которые можно использовать для размещения модуля в новых меню и на новых панелях инструментов доступен в описании API.
В расширении обязательно должны присутствовать функции initGui() и unload() . Эти функции вызываются когда расширение загружается и выгружается.
Файл ресурсов¶
Как видно в примере выше, в initGui() мы использовали иконку из файла ресурсов (в нашем случае он называется resources.qrc ):
Хорошим тоном считается использование префикса, это позволит избежать конфликтов с другими расширениями или с частями QGIS. Если префикс не задан, можно получить не те ресурсы, которые нужны. Теперь сгенерируем файл ресурсов на Python. Это делается командой pyrcc4:
При работе над реальным расширением удобно вести разработку в другом (рабочем) каталоге и создать makefile, который будет генерировать файлы интерфейса и ресурсов, а также выполнять копирование расширения в каталог QGIS.
Документация¶
Этот способ создания документации требует наличия Qgis версии 1.5.
Документацию к расширению можно готовить в виде файлов HTML. Модуль qgis.utils предоставляет функцию showPluginHelp() , которая откроет файл справки в браузере, точно так же как другие файлы справки QGIS.
Кроме того, функция showPluginHelp() может принимать параметр packageName, идентифицирующий расширение, справку которого нужно отобразить; filename, который используется для переопределения имени файла с документацией; и section, для передачи имени якоря (закладки) в документе, на который браузер должен перейти.
Относитесь к файлу конфигурации, использующемуся в приложении, как к разрабатываемому вами коду.
Когда мы разрабатываем программное обеспечение, то всегда прикладываем много усилий для написания качественного и производительного кода. Однако зачастую этого недостаточно.
Разработка качественного программного обеспечения, включает заботу о разработке своей экосистемы, например, для организации процессов тестирования, развертывания, сетевого обмена данными и т.д. Одним из наиболее важных аспектов, который необходимо при этом учитывать, является реализация гибкого механизма управления конфигурацией (настройками) программного обеспечения.
Правильная реализация управления конфигурацией по сути должна позволять запускать программное обеспечение в любой среде без внесения изменений в его исходный код. Этот подход обеспечивает эффективное управление проблемными настройками вашего приложения со стороны администраторов Ops, обеспечивает представление информации о том, что может произойти во время его функционирования, а также позволяет изменять его поведение во время выполнения.
Наиболее распространенные конфигурации включают в себя учетные данные для базы данных или внешней службы, имя хоста сервера, а также любые динамические параметры и т.д.
В этой статье я хочу поделиться с вами несколькими зарекомендовавшими себя практиками управления конфигурациями, а также как мы можем реализовать их в приложениях, написанных на Python.
Когда необходим файл конфигурации приложения?
Перед разработкой конфигурационного файла сначала необходимо спросить себя, нужен ли вообще какой-либо внешний файл с данными? Разве мы не можем просто поместить их в виде константных значений прямо в исходном коде? Собственно, достаточно известная концепция The Twelve-Factor App давно отвечает на этот вопрос:
Лакмусовой бумажкой для проверки правильности решения о выделении config всей конфигурационной информации приложения из кода, является рассмотрение возможности о публикации в любой момент кодовой базы вашего приложения, то есть можно ли сделать его исходный код открытым, без нарушения конфиденциальности чьих-либо учетных данных.
Обратите внимание, что это определение config не включает внутреннюю конфигурацию приложения, такую как, например, как config/routes.rb в Rails, или способ подключения модулей в Spring. Перечисленные выше примеры способов конфигурации не меняются в зависимости от среды развертывания, и поэтому это лучше всего реализовать их в коде.
Подходы рекомендованные этой концепцией предписывают, чтобы любые параметры, зависящие от среды, такие как учетные данные базы данных, находились во внешнем файле. В противном случае их реализуют просто обычными константами в коде. Другой вариант использования, который я часто вижу, – это хранение динамических переменных (данных) во внешнем файле (базе данных), например, черный blacklist или белый whitelist список пользователей. Ими могут быть числа в заданном диапазоне (например, длительность тайм-аута) или любые текстовые файлы с произвольным содержимым. Отметим, что эти динамические переменные (данные) остаются неизменными вне зависимости от особенностей исполняемой среды.
В свою очередь файл конфигурации делает программное обеспечение более гибким и легким для редактирования его функциональных возможностей. Однако, если он слишком сильно разрастается, рациональнее все таки перенести его в базу данных.
Какой формат файла конфигурации использовать?
С практической точки зрения, на формат файла конфигурации нет никаких технических ограничений, если код приложения может его прочитать и анализировать. Но есть и более рациональные практики для выбора формата файла с настройками. Так наиболее распространенными, стандартизованными форматами являются YAML, JSON, TOML и INI. Самый подходящий формата для файл конфигурации должен соответствовать как минимум трем критериям:
- Быть легко читаемым и редактируемым: файл должен иметь текстовый формат и такую структуру, чтобы его содержимое было легко понятно даже не разработчику.
- Разрешать использование комментариев: файл конфигурации – это то, что могут читать не только разработчики. Поэтому в процессе эксплуатации приложения чрезвычайно важно когда пользователи могут успешно пытаться понять его работу и изменить его поведение. Написание комментариев – это эффективный способ быстро пояснить ключевые особенности настройки приложения и делает конфигурационный файл более выразительным.
- Простота развертывания: файл конфигурации должен понятен для обработки всеми операционными системами и средами. Он также должен легко доставляться на сервер с помощью конвейера pipeline CDaaS.
Возможно вам пока не ясно какой из форматов файла лучше использовать. Но если вы подумаете об этом в контексте программирования на языке Python, то наиболее очевидным ответом будет YAML или INI. Форматы YAML и INI хорошо понятны большинству программ и пакетов Python.
INI файл, вероятно, является наиболее простым решением для сохранения настроек приложения, имеющих только один уровень иерархии (вложенности) параметров. Однако формат INI не поддерживает других типов данных, кроме строк: в нем все данные имеют строковое представление.
Та же конфигурация настроек в YAML выглядит следующим образом.
Как видите, YAML изначально поддерживает использование вложенные структуры (также как и JSON) с помощью отступов. Кроме того, YAML, в отличие от формата INI файлов, поддерживает некоторые другие типы данных такие как целые и с плавающей запятой числа, логические значения, списки, словари и т.д.
Формат файлов JSON по сути очень похож на YAML и тоже чрезвычайно популярен, однако в JSON файлы нельзя добавлять комментарии. JSON, как текстовый формат содержащий структурированные данные, часто используется для хранения внутренней конфигурации внутри программы, но совершенно не предназначен для того, чтобы делиться конфигурацией приложения с другими людьми (в особенности с далекими от вопросов разработки ПО).
Формат TOML, с другой стороны, похож на INI, но поддерживает гораздо больше типов данных, а также специальный синтаксис для хранения вложенных структур. Его часто используют менеджеры пакетов Python такие, например, pip или poetry. Но если в файле конфигурации присутствует слишком много вложенных структур, то YAML в этом отношении, с моей точки зрения, наилучший выбор. Следующий ниже фрагмент файла выглядит как INI, но в отличие от него каждое строковое значение имеет кавычки.
Пока что мы выяснили ЧТО из себя представляют форматы файлов YAML, JSON, TOML и INI, далее мы рассмотрим КАК они могут быть использованы.
Как обычно, мы начнем с самого простого, то есть создадим внешний файл с настройками, а затем прочитаем его. Python имеет в своем составе встроенные пакеты для чтения и анализа файлов YAML и JSON. И как видно из приведенного ниже кода, они фактически возвращают один и тот же объект типа dict, поэтому доступ к его атрибутам будет одинаковым для обоих файлов.
Чтение
Из-за проблем с безопасностью рекомендуется использовать метод yaml.safe_load() вместо yaml.load() , чтобы избежать внедрения вредоносного кода при чтении файла конфигурации.
Валидация
При использовании обоих пакетов при попытке чтения несуществующего файла будет генерироваться исключение типа FileNotFoundError . Использование пакета для чтения файлов YAML позволяет получать разные исключения для следующих случаев: пользователь указал файл не являющимся YAML файлом, а также прочитанный файл YAML является не корректным, то есть содержит синтаксические ошибки. В свою очередь пакет для чтения JSON файлов генерирует единственное исключение типа JSONDecoderError для обоих рассмотренных случаев.
Пакет Cofigureparser из состава стандартной библиотеки Python
В этом разделе рассмотрим пакеты, предназначенные непосредственно для управления конфигурацией приложения. И начнем со встроенного в стандартную библиотеку Python пакета: Configureparser.
Configureparser в большинстве случаев используется для чтения и записи INI файлов, и поддерживает чтение входных данных из файла сразу в виде словаря или итерируемого iterable файлоподобного объекта. Как известно, каждый файл INI состоит из нескольких секций, содержащих настройки в виде пар ключ-значение. Ниже приведен простой пример кода для доступа к полям настроек.
Чтение
Как уже нами упоминалось ранее, Configureparser может читать данные настроек в следующих видах на выходе: словаря с помощью метода read_dict() , простой строки с использованием read_string() и итерируемого файлоподобного объекта, возвращаемого методом read_file() .
Валидация
Валидация данных с Configureparser не так проста, как для пакетов, работающих с форматами YAML и JSON. Во-первых, он не возбуждает исключения FileNotFoundError если файла настроек не существует, а вместо этого вызывает исключение типа KeyError, как при попытке доступа к отсутствующему ключу.
Кроме того, этот пакет «игнорирует» некоторые ошибки форматирования, например, неправильное использование отступа. Так в приведенном ниже примере, в случае если в файле присутствует дополнительная табуляция или пробел перед настройкой DEBUG , то вы получите неправильные значения для обеих настроек ENVIRONMENT и DEBUG .
Тем не менее, Configureparser может возбуждать исключение ParserError при наличии нескольких ошибок (см. пример кода с тестами ниже). И в большинстве случаев этого достаточно для определения проблемных мест в самом файле настроек.
Теперь перейдем к сторонним библиотекам, использующимся для управления конфигурацией приложений Python. До сих пор я намеренно пропустил еще один тип файлов конфигурации, а именно .env . Так значения настроек, находящихся в файле .env при запуске терминала (скрипта приложения) будут загружены как переменные среды, и поэтому с помощью библиотеки python-dotenv , а точнее ее метода os.getenv() можно получить доступ к ним из кода приложения.
Файл .env обычно выглядит следующим образом. По умолчанию его местонахождение – корневая папка вашего проекта.
Чтение
Этот тип файла конфигурации очень легко использовать. Так если вы решите переопределить существующую (или создать новую) переменную среды, то можете использовать вызов метод load_dotenv() , например, зададим значение параметра override .
Валидация
Тем не менее пакет python-dotenv не проверяет корректность .env файла. Допустим у вас есть некоторый .env файл (его содержимое представлено ниже), и вы хотите получить доступ к значению переменной (параметра настройки) DEBUG , то будет возвращено значение None без возбуждения исключения соответствующего типа.
Чтение
Dynaconf использует .env файл для поиска других конфигурационных файлов и последующего заполнения полей settings объекта с настройками. Так если в двух файлах настроек есть одна и та же переменная, то ее значение будет перезаписано значением из последнего файла настроек.
Валидация
Одна из наиболее интересных, в частности для меня, возможностей dynaconf – это его настраиваемый валидатор. Как упоминалось ранее, Configureparser недостаточно строго проверяет корректность INI файлов настроек, но это можно легко реализовать в dynaconf. В следующем примере мы проверяем, существуют ли определенные ключи в файле с настройками и имеется ли в нем конкретный ключ с корректным значением. Если вы читаете настройки из файла YAML или TOML, которые как мы говорили ранее, поддерживают несколько типов данных, то вы даже можете проверить, находится ли значение настройки, например, число в заданном диапазоне.
Интеграция с Pytest
Еще одна интересная особенность dynaconf – это возможность его интеграции с pytest. Так настройки для модульного тестирования unit testing обычно существенно отличаются в различных средах. Для этого вы можете использовать параметр FORCE_ENV_FOR_DYNACONF , чтобы ваше приложение могло прочитать значения настроек из внешнего файла, или использовать фикстуру monkeypatch для замены определенных пар ключ и значение в файле настроек.
Обновляем конфигурацию приложения во время его выполнения
Dynaconf в своем составе содержит метод reload() , который очищает значения настроек и перезапускает все загрузчики вашего приложения. Это полезно, если вы хотите, чтобы приложение перезагружало файл настроек во время выполнения и соответственно в последствие изменяло свое поведение. Например, приложение должно автоматически перезагрузить настройки, если файл конфигурации был открыт и изменен (откорректирован).
Рассмотрим последним, в этой статье, способ создания и поддержки конфигурации для вашего приложения, который по сути является гораздо большим, чем просто загрузчик и парсер файлов с настройками.
Hydra – это платформа, разработанная Facebook для гибкой и элегантной настройки самых сложных приложений. Которая помимо чтения, записи и валидации корректности файлов конфигурации, реализовывает свою достаточно рациональную стратегию упрощения управления несколькими конфигурационными файлами, переопределения (перезаписи) их с использованием интерфейса командной строки, создания snapshot снимка состояния приложения перед каждым его запуском (между перезапусками) и т.д.
Чтение
Рассмотрим основы использования hydra. Так в следующем примере команда +APP.NAME , добавленная в командную строку при запуске скрипта, позволяет добавить новое поле (настройку) в конфигурацию приложения, а также осуществить перезапись значения существующего поля (значения настройки) APP.NAME=hydra1.1 .
Валидация
Hydra прекрасно интегрируется с декоратором @dataclass для выполнения основных проверок корректности, таких как проверка типов или значения полей. Однако у нее нет поддержки __post_init__ метода расширенной проверки значений, как это описано в моей предыдущей статье.
Группа конфигураций
Hydra вводит концепцию под названием config group . Идея которой состоит в том, чтобы сгруппировать файлы конфигурации одного типа (или для выполнения одних задач) и затем выбирать один из них во время выполнения приложения. Например, у вас имеется группа настроек «Базы данных» с одной конфигурацией для Postgres, а другой для MySQL.
Когда конфигурация приложения станет более сложной, то в вашей программе она может иметь следующую структуру (пример из документации Hydra).
Например, вы хотите протестировать свое приложение с различными комбинациями опций db , schema и ui , это можно сделать следующим образом:
Далее…
Hydra поддерживает использование нескольких наборов параметров конфигурации с опцией --multirun , при этом запускаются параллельно несколько задач с различными файлами конфигурации. Например, для предыдущего примера мы можем запустить скрипт следующим образом:
В этом случае в основном потоке запускаются 6 задач одновременно:
Вывод
В этой статье мы рассмотрели несколько способов управления конфигурацией приложений в Python. Независимо от того какой из них вы выберете, всегда необходимо думать о удобочитаемости файлов конфигурации, дальнейшей их поддержки, а также способах обнаружения ошибок для случаев их некорректного использования. Таким образом, конфигурационный файл – это по сути еще один тип кода.
Надеюсь, вам понравится эта статья, не стесняйтесь оставлять свои комментарии ниже.
Python – отличный инструмент для обработки данных. Вполне вероятно, что программа, которую вы пишете, будет управлять данными или выполнять операции чтения и записи. Потому особенно полезно знать, как Python обрабатывает различные форматы файлов, в которых хранятся разные типы данных.
Для примера представим программу Python, которая проверяет список пользователей для контроля доступа. Список пользователей, вероятно, будет храниться в текстовом файле. Ещё один пример: программа для выполнения финансового анализа получает вводные данные из сохраненной таблицы. Как видите, вне зависимости от приложения, входные и выходные данные задействованы практически всегда.
В данном руководстве речь идёт о типах форматов, которые поддерживает Python 3. Также руководство научит вас обрабатывать текстовые файлы.
Требования
Для выполнения руководства вам понадобится предварительно настроенная среда Python 3. Все необходимые инструкции вы найдёте в следующих статьях:
Форматы файлов в Python 3
Python очень гибкий и может относительно легко обрабатывать множество различных форматов файлов. Вот основные форматы:
Формат | Описание |
txt | Обычный текстовый файл, который хранит данные в виде символов (или строк) и исключает структурированные метаданные. |
CSV | Файл, который хранит данные в виде таблицы; для структурирования хранимых данных используются запятые (или другие разделители). |
HTML | Файл Hypertext Markup Language хранит структурированные данные; такие файлы используются большинством сайтов. |
JSON | Простой файл JavaScript Object Notation, один из наиболее часто используемых форматов для хранения и передачи данных. |
Данное руководство рассматривает только формат txt.
1: Создание текстового файла
Сначала нужно создать тестовый файл для работы. Откройте текстовый редактор и создайте файл days.txt. Добавьте в новый файл список дней недели:
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
Сохраните файл и запомните его местонахождение (это нужно для дальнейшей работы). В данном случае файл будет храниться в каталоге /users/8host/days.txt.
2: Открытие файла
Создайте сценарий files.py в текстовом редакторе и для простоты сохраните его в тот же каталог (/users/8host/).
Чтобы открыть файл в Python, нужно связать файл на диске с переменной Python. Сначала сообщите Python, где находится нужный файл. Чтобы открыть какой-либо файл, Python должен знать путь к этому файлу. Путь к файлу days.txt выглядит так: /users/8host/days.txt.
В файле files.py создайте переменную path и укажите в ней путь к файлу days.txt.
Теперь можно использовать функцию open(), чтобы открыть файл days.txt. В качестве первого аргумента функция open() требует путь к файлу, который нужно открыть. Эта функция имеет много других параметров. Одним из основных параметров является режим; это опциональная строка, которая позволяет выбрать режим открытия файла:
3: Чтение файла
Теперь вы можете работать с файлом. В зависимости от режима, в котором открыт файл, вы можете выполнить в нём те или иные действия. Для чтения информации Python предлагает три взаимосвязанные операции.
Прочитав первую строку файла, операция readline при следующем запуске выведет вторую строку.
days_file.readlines()
['Monday\n', 'Tuesday\n', 'Wednesday\n', 'Thursday\n', 'Friday\n', 'Saturday\n', 'Sunday\n']
Читая файлы в Python, важно помнить следующее: если файл был прочитан с помощью одной из операций чтения, его нельзя прочитать снова. К примеру, если вы запустили days_file.read(), а затем days_file.readlines(), вторая операция вернёт пустую строку. Потому нужно открывать новую переменную файла всякий раз, когда вы хотите прочитать данные из файла.
4: Запись в файл
Теперь попробуйте создать новый файл, который будет включать заголовок Days of the Week. Сначала создайте переменную title в файле files.py.
title = 'Days of the Week\n'
Сохраните дни недели в строковой переменной days. Ниже показан код из всех вышеупомянутых разделов (чтобы было понятнее); файл открывается в режиме чтения, выходные данные операции чтения сохраняются в новой переменной days.
path = '/users/8host/days.txt'
days_file = open(path,'r')
days = days_file.read()
new_path = '/users/8host/new_days.txt'
new_days = open(new_path,'w')
Функция откроет файл, после чего вы можете записать в него данные с помощью операции <file>.write(). Операции записи необходим всего один параметр – строка, которую нужно записать в файл. Чтобы начать новую строку в файле, нужно явно использовать символ новой строки. Запишите в файл files.py заголовок и добавьте пару операторов print.
new_days.write(title)
print(title)
new_days.write(days)
print(days)
После этого нужно закрыть файл.
5: Закрытие файла
Операция закрытия файла прерывает соединение между файлом на диске и переменной. Закрытые файлы могут использоваться другими программами, кроме того, это обеспечивает безопасность данных. закрыть файл можно с помощью функции <file>.close(). Добавьте в файл files.py:
6: Проверка кода
Прежде чем запустить сценарий files.py, убедитесь, что его содержимое выглядит так:
path = '/users/8host/days.txt'
days_file = open(path,'r')
days = days_file.read()
new_path = '/users/8host/new_days.txt'
new_days = open(new_path,'w')
title = 'Days of the Week\n'
new_days.write(title)
print(title)
new_days.write(days)
print(days)
days_file.close()
new_days.close()
Сохраните код, откройте терминал и запустите сценарий Python:
В терминале появится вывод:
Days of the Week
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
Теперь попробуйте открыть файл new_days.txt. Если всё работает должным образом, файл будет выглядеть так:
Days of the Week
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
Заключение
Теперь вы умеете обрабатывать и управлять простыми текстовыми файлами в Python 3: открывать и читать файлы, записывать в них новые данные и закрывать их.
Python - замечательный язык программирования. Одной из самых слабых его сторон является пакеты. Это общеизвестный факт в сообществе. Установка, импорт, использование и создание пакетов улучшилась с годами, но она по-прежнему не соответствует новым языкам, таким как Go и Rust, которые могут многому научиться из-за проблем Python и других более зрелых языков.
В этом уроке вы узнаете все, что вам нужно знать, чтобы создавать и делиться своими собственными пакетами. Для общей информации о пакетах Python ознакомьтесь с разделом «Как использовать пакеты Python».
Упаковка проекта
Упаковка проекта - это процесс, с помощью которого вы берете надежно согласованный набор модулей Python и, возможно, других файлов и помещаете их в структуру, которую можно легко использовать. Существуют различные вещи, которые вы должны учитывать, такие как зависимости от других пакетов, внутренняя структура (подпакеты), управление версиями, целевая аудитория и форма пакета (исходный код и/или двоичный файл).
Пример
Начнем с быстрого примера. Пакет conman представляет собой пакет для управления конфигурацией. Он поддерживает несколько форматов файлов, а также распределенную конфигурацию с помощью etcd.
Содержимое пакета обычно хранится в одной директории (хотя обычно для разделения подпакетов в нескольких каталогах), а иногда, как и в этом случае, в собственном репозитории git.
Корневой каталог содержит различные файлы конфигурации ( setup.py является обязательным и наиболее важным), а сам код пакета обычно находится в подкаталоге, имя которого является именем пакета и в идеале является каталогом тестов. Вот как это выглядит для «conman»:
Давайте быстро заглянем в файл setup.py. Он импортирует две функции из пакета setuptools: setup() и find_packages() . Затем он вызывает функцию setup() и использует find_packages() для одного из параметров.
Это довольно нормально. Хотя файл setup.py является обычным файлом Python, и вы можете делать все, что хотите, его основное задание - вызвать функцию setup() с соответствующими параметрами, поскольку он будет запускаться различными инструментами стандартным способом при установке вашего пакета. Я расскажу подробности в следующем разделе.
Файлы конфигурации
В дополнение к setup.py есть еще несколько дополнительных файлов конфигурации, которые могут отображаться здесь и обслуживать различные цели.
Setup.py
Функция setup() принимает большое количество именованных аргументов для управления многими аспектами установки пакета, а также для запуска различных команд. Многие аргументы указывают метаданные, используемые для поиска и фильтрации при загрузке вашего пакета в репозиторий.
- name: имя вашего пакета (и как оно будет указано в PYPI)
- version: это важно для поддержания правильного управления зависимостями
- url: URL вашего пакета, обычно GitHub или URL-адрес readthedocs
- packages: список подпакетов, которые необходимо включить; здесь помогает find_packages()
- setup_requires: здесь вы указываете зависимости
- test_suite: какой инструмент запускается во время тестирования
long_description устанавливается здесь на содержимое файла README.md , что является наилучшей практикой для использования одного источника правды.
setup.cfg
Файл setup.py также поддерживает интерфейс командной строки для запуска различных команд. Например, чтобы запустить модульные тесты, вы можете ввести: python setup.py test
Файл setup.cfg является файлом формата ini, который может содержать параметры по умолчанию для команд, которые вы передаете setup.py . Здесь setup.cfg содержит некоторые опции для nosetests (наш тестовый раннер):
MANIFEST.in
Этот файл содержит файлы, которые не являются частью внутреннего каталога пакетов, но вы все еще хотите включить его. Обычно это файл readme , файл лицензи Важным файлом является файл requirements.txt . Этот файл используется pip для установки других необходимых пакетов.
Вот файл MANIFEST.in в conman:
Зависимости
Вы можете указать зависимости как в разделе install_requires файла setup.py , так и в файле requirements.txt . Pip установит автоматически зависимости от install_requires , но не из файла requirements.txt . Чтобы установить эти требования, вам нужно будет указать его явно при запуске pip install -r requirements.txt .
Параметр install_requires предназначен для указания минимальных и более абстрактных требований на основном уровне версии. Файл requirements.txt предназначен для более конкретных требований, часто с привязкой к второстепенным версиям.
Вот файл требований conman. Вы можете видеть, что все версии зафиксированы, что означает, что это может негативно повлиять, если один из этих пакетов обновится и внесет изменения, которые ломают conman.
Пиннинг дает вам предсказуемость и спокойствие. Это особенно важно, если многие люди устанавливают ваш пакет в разное время. Без закрепления каждый человек получит различное сочетание версий зависимостей на основе того, когда они его установили. Недостатком пиннинга является то, что если вы не справляетесь с развитием зависимостей, вы можете застрять на старой, плохо исполняющейся и даже уязвимой версии некоторой зависимости.
Я изначально написал conman в 2014 году и не обращал на него особого внимания. Теперь для этого урока я обновил все, и для почти каждой зависимости были некоторые существенные улучшения.
Распределения
Вы можете создать дистрибутив источника или бинарный дистрибутив. Я расскажу об обоих.
Распределение источников
Вы создаете исходный дистрибутив с помощью команды: python setup.py sdist . Вот вывод для conman:
Как вы можете видеть, я получил одно предупреждение о том, что отсутствует файл README с одним из стандартных префиксов, потому что мне нравится Markdown, поэтому вместо этого у меня есть «README.md». Кроме этого, все исходные файлы пакета были включены и дополнительные файлы. Затем в каталоге conman.egg-info была создана куча метаданных. Наконец, создается сжатый tar-архив под названием conman-0.3.tar.gz и помещается в подкаталог dist .
Для установки этого пакета потребуется шаг сборки (хотя это чистый Python). Вы можете установить его с помощью pip, просто передав путь к пакету. Например:
Conman был установлен в site-packages и может быть импортирован как любой другой пакет:
Wheels
Wheels - относительно новый способ упаковки кода Python и, возможно, C-расширений. Они заменяют формат egg. Существует несколько типов колес: чистые колеса Python, платформы и универсальные колеса. Чистые колеса Python - это пакеты, такие как conman, у которых нет кода расширения C.
Платформенные колеса имеют код расширения C. Универсальные колеса - это чистые колеса Python, которые совместимы как с Python 2, так и с Python 3 с одинаковой базой кода (они не требуют даже 2to3). Если у вас есть чистый пакет Python и вы хотите, чтобы ваш пакет поддерживал как Python 2, так и Python 3 (становится все более и более важным), вы можете создать единую универсальную сборку вместо одного колеса для Python 2 и одного колеса для Python 3.
Если в вашем пакете есть код расширения C, вы должны создать колесо платформы для каждой платформы. Огромное преимущество колес, особенно для пакетов с расширениями C, заключается в том, что нет необходимости иметь компилятор и поддерживающие библиотеки, доступные на целевой машине. Колесо уже содержит встроенный пакет. Таким образом, вы знаете, что его гораздо быстрее установить, потому что это буквально просто копия. Люди, которые используют научные библиотеки, такие как Numpy и Pandas, действительно могут это оценить, поскольку установка таких пакетов требует много времени и может быть неудачной, если какая-то библиотека отсутствует или компилятор не настроен должным образом.
Команда для создания чистых или платформенных колес: python setup.py bdist_wheel .
Setuptools - движок, который обеспечивает функцию setup() , будет автоматически обнаруживаться, если требуется чистое или платформенное колесо.
При проверке каталога dist вы можете увидеть, что было создано чистое колесо Python:
Название «conman-0.3-py2-none-any.whl» имеет несколько компонентов: имя пакета, версию пакета, версию Python, версию платформы и, наконец, расширение «whl».
Чтобы создавать универсальные пакеты, вы просто добавляете --universal , как в python setup.py bdist_wheel --universal .
Полученное колесо называется "conman-0.3-py2.py3-none-any.whl".
Обратите внимание, что вы несете ответственность за то, чтобы ваш код действительно работал как с Python 2, так и с Python 3, если вы создаете универсальный пакет.
Заключение
Написание собственных пакетов Python требует использования большого количества инструментов, определения большого количества метаданных и тщательного анализа ваших зависимостей и целевой аудитории. Но награда велика.
Если вы правильно напишите полезный код и упакуете его, люди смогут легко его установить и извлечь из него выгоду.
Довольно часто при разработке возникает необходимость программно создать какой-то документ или внести изменения в уже существующий. Работая с текстами разной направленности из кода, нужно принять во внимание, что тексты иногда хранятся в более сложных форматах, чем .txt . Они могут содержать встроенное форматирование, быть разделенными на страницы, перемежаться медиаконтентом (графиками, рисунками).
Python умеет работать со многими такими документами. Давайте посмотрим, что можно сделать, чтобы создавать документы в формате Word, Excel или PowerPoint прямо из Python.
Стоит отметить, что форматы . docx , . xlsx и . pptx открытые, что позволяет разработчикам довольно просто писать библиотеки для работы с ними. Для каждого офисного формата есть несколько библиотек с разным функционалом, и мы рассмотрим лишь некоторые из них.
2. Создание текстового документа
Давайте воспользуемся модулем python-docx для создания docx -документа. Он, как и остальные приведенные в данном уроке библиотеки, не входит в состав стандартной библиотеки и требует отдельной установки через
После установки давайте рассмотрим вот такой пример:
Ключевой элемент этой библиотеки — объект Document . Для создания нового документа формата . docx надо записать результат вызова Document в переменную. Этого достаточно для создания абсолютно пустого документа в памяти. Чтобы наполнить его содержимым, необходимо вызывать у получившегося объекта различные методы, например:
- add_heading — для создания заголовков разного уровня. При этом уровень 0 — заголовок документа
- add_paragraph — для создания абзацев. С помощью параметра style можно управлять стилем абзаца и превращать его элемент маркированного или нумерованного списка
Метод add_paragraph объекта-документа возвращает новый абзац, у которого есть свои методы вроде add_run , который дописывает текст с форматированием или без него в конец абзаца.
Метод add_table создает в документе таблицу размером col столбцов и row строк. Если мы присвоим результат вызова этой функции переменной, сможем заполнить такую таблицу данными.
Метод save сохраняет документ под указанным именем.
Выполните приведенный код. Затем откройте созданный файл test.docx. Вы должны увидеть что-то такое:
С помощью python-docx можно не только создавать новые документы, но и открывать уже существующие. Для этого при создании документа надо в качестве параметра передать путь к файлу или просто его имя, если он находится в каталоге с программой.
Таким образом, мы можем получить абзацы или другие элементы документа, пройтись по ним и получить либо изменить какую-то информацию:
Как мы увидим дальше, работа с подобными модулями примерно одинакова. Все элементы управления и форматирования:
есть в наличии в том или ином виде, их можно изменять и комбинировать.
3. Работа с документом как с шаблоном
Очень распространенным вариантом использования является не создание документа с нуля, а заполнение данными уже готового шаблона. Для этого можно использовать библиотеку docxtpl .
Например, у нас есть вот такой шаблон приглашения на мероприятие:
C помощью двойных фигурных скобок выделены места в документе, куда мы можем подставить свои данные по имени. Кроме того, шаблоны поддерживают специальный синтаксис для циклов, условий и других конструкций. Внутри docxtpl лежит мощный и простой в использовании движок шаблонов jinja2.
При работе с этой библиотекой нам надо воспользоваться классом DocxTemplate, при создании экземпляра которого необходимо передать имя нашего документа, который содержит шаблон.
После чего нужно создать словарь и заполнить его информацией для вставки в документ. Значения из нашего словаря будут подставляться в шаблон по ключу. Метод render как раз и отвечает за такое заполнение. Метод save сохраняет документ под переданным именем.
В итоге у нас получится вот такой документ:
4. Создание презентаций
Для работы с презентациями формата .pptx в Python есть библиотека python-pptx.
Принцип ее работы во многом схож с библиотекой python-docx, но здесь ключевым элементом, с которым идет работа, выступает не Document, а Presentation.
Напишем следующий код:
Обратиться к слайдам презентации можно через атрибут slides презентации. В свою очередь у slides есть метод add_slide, который добавляет новый слайд в презентацию. Данный метод принимает на вход схему нового слайда.
Подробнее о схемах слайдов смотрите в документации. Но, например, нулевая схема предназначена для создания заголовочного слайда, а восьмая — для слайда с изображением.
На слайде, в зависимости от схемы, по которой он создан, могут быть разные контейнеры для содержимого, которые называются placeholders . Бывают контейнеры для текста, изображения, таблицы или графика. У текстового контейнера SlidePlaceholder есть свойство text, которое задает текст.
У контейнера для изображения PicturePlaceholder есть метод insert_picture , который добавляет переданное изображение на слайд.
Метод save презентации сохраняет презентацию под переданным именем.
Вот такая презентация у нас получится в итоге:
Как и в случае с документами, мы можем открыть уже существующую презентацию и получить или изменить какие-либо данные.
5. Создание таблиц Excel
Для работы с файлами формата .xlsx есть несколько библиотек, одна из них — xlsxwriter , предназначенная только для создания xlsx-файлов.
Принцип работы с этой библиотекой очень схож с рассмотренными ранее, но с небольшими оговорками. Уже при создании документа нам необходимо передавать имя, под которым этот документ будет сохранен в конце.
Потом с помощью метода add_worksheet надо добавить страницу в документ. У добавленной страницы можно вызывать метод write , который записывает в определенную строку и колонку переданные данные.
С помощью метода add_chart можно создать диаграмму, указав ее тип и данные для построения. После чего построенную диаграмму можно добавить на страницу с помощью метода insert_chart с указанием ячейки вставки и самой диаграммы.
Читайте также: