В этой статье мы рассмотрим некоторые концепции, используемые при структурировании нашего кода Python с использованием модулей и пакетов. Мы научимся создавать собственные модули, определять функции и классы и использовать их в других модулях и пакетах. Мы также рассмотрим, как создавать пакеты, организовывая связанные модули в каталоге, и как импортировать модули из пакетов. Наконец, мы рассмотрим некоторые встроенные модули и пакеты Python.
К концу этого руководства у нас будет четкое понимание того, как структурировать наш код с использованием модулей и пакетов, что значительно расширит наши возможности писать поддерживаемый, повторно используемый и читаемый код.
- Представляем модули и пакеты
- Работа с модулями
- Создание простого модуля
- Использование оператора импорта
- Использование ключевого слова from
- С использованием as
- Представляем пакеты
- Создание и управление пакетами
- Создание пакетов и подпакетов
- Импорт из пакетов
- Абсолютный импорт
- Относительный импорт
- Атрибут __all___
- Использование __all__атрибута в модулях
- Использование __all__атрибута в пакетах
- Стандартная библиотека Python и популярные сторонние пакеты
- Индекс пакетов Python и сторонние пакеты
- Упаковка и распространение
- инструменты настройки для упаковки
- twine для публикации
- Заключение
Представляем модули и пакеты
Модуль в Python — это отдельный файл, содержащий код Python в виде функций, исполняемых операторов, переменных и классов. Модуль действует как автономная единица кода, которую можно импортировать и использовать в других программах или модулях.
Пакет, с другой стороны, представляет собой набор модулей, организованных в каталоге. Пакеты позволяют нам группировать несколько связанных модулей вместе в общем пространстве имен, что упрощает организацию и структурирование нашей базы кода.
Разбиение кода на модули и пакеты дает огромные преимущества:
- Ремонтопригодность. Разбиение кода на модули помогает нам вносить изменения в независимые части общего приложения, не затрагивая все приложение, поскольку модули предназначены только для работы только с одной частью приложения.
- Многоразовое использование. Это ключевая часть разработки программного обеспечения: мы пишем код один раз и можем использовать его в разных частях приложения столько раз, сколько захотим. Это позволяет нам писать чистый и сухой код.
- Сотрудничество. Модульный код расширяет возможности совместной работы. Разные команды могут одновременно работать над разными частями одного и того же приложения, не мешая работе друг друга.
- Читабельность. Разбиение кода на модули и пакеты повышает читаемость кода. Мы можем легко определить, что происходит в файле. Например, у нас может быть файл с именем databaseConnection.py: уже по имени мы можем сказать, что этот файл имеет дело с подключениями к базе данных.
Работа с модулями
Модули можно импортировать и использовать в других программах, модулях и пакетах. Они очень полезны для приложения, поскольку разбивают функцию приложения на более мелкие, управляемые и логические единицы.
Например, предположим, что мы хотим создать веб-приложение: приложению понадобится код для подключения к базе данных, код для создания моделей базы данных, код, который будет выполняться, когда пользователь посещает определенный маршрут, и так далее.
Мы можем поместить весь код в один файл, но тогда код очень быстро станет неподдерживаемым и нечитаемым. Используя модули, мы можем разбить код на более управляемые блоки. Весь код, необходимый для подключения к базе данных, мы поместим в один файл, код моделей базы данных — в другой файл, а код маршрутов — в модуль. Разбиение кода на эти модули способствует организации, повторному использованию и удобству сопровождения.
Создание простого модуля
Создать модуль на Python довольно просто. Допустим, у нас есть несколько связанных функций, переменных и классов: мы могли бы поместить их в один модуль и дать этому модулю любое имя, но желательно давать нашим модулям описательные имена — так же, как в случае с функциями, переменными и классами.
Чтобы создать модуль в Python, откройте IDE или текстовый редактор, создайте файл и присвойте ему описательное имя и расширение.py. В этом примере давайте вызовем его sample.pyи введем следующий код:
# sample.py # create a variable in the module sample_variable = "This is a string variable in the sample.py module" # A function in the module def say_hello(name): return f"Hello, {name} welcome to this simple module." # This is another function in the module def add(a, b): return f"The sum of {a} + {b} is = {a+b}" print(sample_variable) print(say_hello("kabaki")) print(add(2, 3))
Приведенный выше код определяет модуль с именем sample.py. Он содержит переменную с именем sample_variable, значением которой является строка «This is a string variable in the sample.py module». Этот модуль также содержит два определения функций. При вызове say_hello()функция принимает параметр имени и возвращает приветственное сообщение, если мы передаем ей имя. Функция add()возвращает сумму двух переданных ей чисел.
Хотя модули предназначены для использования в других частях программы или приложения, мы можем запускать их независимо. Чтобы запустить этот модуль, нам необходимо установить Python в нашей среде разработки. Мы можем запустить его на терминале, используя следующую команду:
python sample.py
Или мы можем использовать следующую команду:
python3 sample.py
Это вернет следующий вывод:
This is a string variable in the sample.py module Hello, kabaki welcome to this simple module. The sum of 2 + 3 is = 5
Для одноразового использования модуля мы можем запустить его как отдельный, но большинство модулей предназначены для использования в других модулях или других частях программы Python. Таким образом, чтобы использовать переменные, функции и классы из одного модуля в другом модуле, нам необходимо импортировать модуль. Существуют разные способы импорта модулей, давайте их рассмотрим.
Использование оператора импорта
Мы можем использовать этот importоператор, чтобы сделать содержимое одного модуля доступным для использования в другом модуле. Рассмотрим наш sample.pyвариант сверху: чтобы использовать его содержимое в другом модуле, мы просто импортируем его:
# another_module.py import sample print(sample.sample_variable) print(sample.say_hello(“John”)) print(sample.add(2, 3))
В приведенном выше коде показано, как использовать importфункции из sample.pyмодуля, делая их доступными для использования в another_module.py. Обратите внимание: когда мы импортируем модуль, мы не включаем расширение.py; Python автоматически узнает, что мы импортируем модуль.
Использование ключевого слова from
Мы также можем использовать fromключевое слово для импорта определенных функций или переменных. Допустим, в модуле определено большое количество функций и переменных, и мы не хотим использовать их все. Мы можем указать функции или переменные, которые хотим использовать, используя fromключевое слово:
# another_module.py from sample import add print(add(10, 4))
Приведенный выше код показывает, что мы специально импортировали add()функцию из sampleмодуля.
Еще одним преимуществом использования fromключевого слова является то, что мы запустим импортированную функцию без пространства имен или префикса с именем ее родительского модуля. Вместо этого мы будем использовать функцию так, как мы определили ее в файле, в котором мы ее используем. Это приводит к более краткому и читаемому коду.
С использованием as
Мы можем использовать его asдля предоставления псевдонима или альтернативного имени модуля.
Иногда мы можем определять имена модулей, которые являются довольно длинными или нечитаемыми. Python предоставляет возможность предоставить импортируемому модулю альтернативу или псевдоним, который мы можем использовать для ссылки на них в модулях, в которые мы их импортируем. Для этого мы будем использовать asключевое слово:
# another_module.py import sample as sp result = sp.add(5, 5) print(result) print(sp.say_hello("Jason"))
Этот код показывает импорт модуля sample, где модулю присваивается альтернативное имя sp. Таким образом, использование sp— это то же самое, что вызов sample. Таким образом, используя псевдоним, мы имеем доступ к переменным и функциям точно так же, как если бы использовали исходное имя.
Используя эти три метода, мы можем использовать переменные или функции из одного модуля в другом модуле, повышая читаемость нашего приложения, поскольку нам не нужно помещать код в один файл.
При именовании наших модулей рекомендуется использовать строчные буквы и отдельные слова с подчеркиванием. Например, если у нас есть модуль для обработки подключений к базе данных, мы можем назвать его database_connection.py. Чтобы избежать конфликтов имен, старайтесь выбирать для модулей описательные и уникальные имена. Если имя модуля может привести к конфликту имени со встроенным ключевым словом Python или модулем из сторонней библиотеки, рассмотрите возможность использования другого имени или добавления префикса, соответствующего проекту. Кроме того, помните, что имена в Python чувствительны к регистру, поэтому при импорте обязательно используйте правильное имя модуля.
В целом, использование модулей позволяет нам создавать и организовывать наш код таким образом, чтобы он был читабельным и удобным в сопровождении. И это очень полезно — работаем ли мы над небольшим скриптом или большим приложением. Позже мы рассмотрим некоторые распространенные модули стандартной библиотеки Python.
Представляем пакеты
Пакет в Python — это способ организации связанных модулей в каталоге. Это обеспечивает лучший способ организации кода, позволяя нам группировать модули, которые служат общей цели или являются частью одного и того же компонента.
Пакеты особенно полезны при структурировании крупных проектов или библиотек. Например, рассмотрим случай веб-приложения, в котором у нас есть код для различных моделей баз данных, представлений и утилит.
Было бы очень разумно, если бы мы создали пакет моделей с разными модулями для разных моделей в приложении. Допустим, наше веб-приложение представляет собой приложение для ведения блога: возможными моделями могут быть модель пользователей и модель сообщений; затем мы создадим модуль для управления пользователями и модуль для управления сообщениями, а затем поместим их в пакет моделей.
Здесь важно еще раз подчеркнуть, что модули — это отдельные файлы, содержащие код Python: они помогают поместить связанные функции, классы и переменные в один файл. Напротив, пакеты — это каталоги, содержащие несколько модулей или подпакетов. Они обеспечивают более высокий уровень организации нашего кода, группируя связанные модули и позволяя нам создавать более структурированные и удобные в сопровождении проекты.
Создание и управление пакетами
Хотя пакеты организуют связанные модули кода в одном каталоге, простое размещение модулей в каталоге не делает его пакетом. Чтобы Python мог идентифицировать каталог как пакет или подпакет, этот каталог должен содержать специальный файл с именем __init__.py.
Этот файл уведомляет Python о том, что содержащий его каталог следует рассматривать как пакет или подпакет. Этот файл может быть пустым, и в большинстве случаев так оно и есть, но он также может содержать код инициализации и играет жизненно важную роль в структуре пакета Python и механизмах импорта. Таким образом, using __init__.pyсообщает Python, что мы намеренно создаем пакет, тем самым помогая ему отличить пакет от обычного каталога.
Пакеты могут иметь иерархическую структуру, то есть мы можем создавать подпакеты внутри наших пакетов для дальнейшей организации нашего кода. Это обеспечивает более точное и контролируемое разделение компонентов и функций. Рассмотрим следующий пример:
my_package/ ├── __init__.py ├── module1.py └── subpackage/ ├── __init__.py ├── submodule1.py └── submodule2.py
На этой диаграмме показано my_package, что это основной пакет и subpackageего подпакет. В обоих каталогах есть __init__.pyфайл. Использование такой структуры помогает нам организовать наш код в значимую иерархию.
Создание пакетов и подпакетов
Чтобы создать пакет, мы сначала создаем каталог, в котором будут храниться наши модули. Затем создаем __init__.pyфайл. Затем мы создаем в нем наши модули вместе со всеми подпакетами.
Допустим, мы создаем приложение-калькулятор: давайте создадим пакет для различных вычислений, поэтому создайте каталог в нашем терминале или нашей IDE и назовите его calculator.
В каталоге создайте __init__.pyфайл, затем создайте несколько модулей. Давайте создадим три модуля: add.py, subtract.py, и multiply.py. В итоге у нас будет структура каталогов, подобная этой:
calculator/ ├── __init__.py ├── add.py ├── subtract.py └── multiply.py
Давайте поместим несколько образцов в эти файлы. Откройте add.pyмодуль и вставьте следующий код:
# add.py def add(a, b): """ Adds two numbers and returns the result. :param a: First number. :param b: Second number. :return: Sum of a and b. """ return a + b
При этом создается модуль для сложения, отделяющий его от других вычислений. Создадим еще один модуль для вычитания. Откройте subtract.pyфайл и вставьте в него следующий код:
# subtract.py def subtract(a, b): """ Subtracts two numbers and returns the result. :param a: First number. :param b: Second number. :return: Difference of a and b. """ return a - b
Итак, в нашем приложении, если мы хотим воспользоваться преимуществами модулей калькулятора, мы просто импортируем пакет. Существуют разные способы импорта из пакета, поэтому давайте рассмотрим их в следующем разделе.
Импорт из пакетов
Импортировать модули из пакетов или подпакетов можно двумя основными способами. Мы можем использовать либо относительный импорт, либо абсолютный импорт.
Абсолютный импорт
Абсолютный импорт используется для прямого импорта модулей или подпакетов из пакета верхнего уровня, где мы указываем полный путь к модулю или пакету, который мы хотим импортировать.
Вот пример импорта addмодуля из calculatorпакета:
# calculate.py from calculator.add import add result = add(5, 9) print(result)
В приведенном выше примере показан внешний модуль — calculate.py— который импортирует add()функцию из addмодуля, используя абсолютный импорт, указав абсолютный путь к функции.
Относительный импорт
Относительный импорт используется для импорта модулей или пакетов относительно текущего положения модуля в иерархии пакетов. Он указывается с помощью точек (.), обозначающих уровень относительного позиционирования.
Чтобы продемонстрировать относительный импорт, давайте создадим подпакет в пакете calculator, вызовем его multiply, затем переместим multiply.pyмодуль в этот подпакет, чтобы у нас была обновленная структура пакета, подобная этой:
calculator/ ├── __init__.py ├── add.py ├── subtract.py └── multiply/ ├── __init__.py └── multiply.py
Благодаря этой настройке мы теперь можем использовать относительный импорт для доступа к multiplyмодулю из других модулей пакета calculatorили его подпакетов. Например, если бы внутри calculatorпакета был модуль, который необходимо импортировать multiply, мы могли бы использовать следующий код:
from .multiply import multiply result = multiply(5, 9) print(result)
В целом, относительный импорт особенно полезен для импорта внутри структуры пакета и подпакета.
Атрибут __all___
Бывают случаи, когда мы можем использовать все модули из пакета или подпакетов или все функции и переменные из модуля, поэтому ввод всех имен становится довольно громоздким. Итак, нам нужен способ указать, что мы импортируем функции и переменные, которые может предложить модуль, или все модули, которые предлагает пакет.
Чтобы настроить, что можно импортировать, когда пользователь хочет импортировать все предложения из модуля или пакета, в Python есть атрибут, __all__который представляет собой специальный атрибут, который используется в модулях или пакетах для управления тем, что импортируется, когда пользователь использует оператор from module import *. Этот атрибут позволяет нам указать список имен, которые будут считаться «общедоступными» и будут импортироваться при *использовании импорта с подстановочным знаком ( ).
Использование __all__атрибута в модулях
В модуле мы можем определить __all__ атрибут, чтобы явно указать, какие имена следует импортировать при from module import *использовании оператора. Это помогает предотвратить непреднамеренный импорт внутренних имен, обеспечивая четкий способ отображения функций, которые можно импортировать публично, и тех, которые предназначены для использования только в модуле.
Вот пример:
# my_module.py __all__ = ['public_function', 'public_variable'] def public_function(): return "This is a public function." def _internal_function(): return "This is an internal function." public_variable = "This is a public variable." _internal_variable = "This is an internal variable."
В приведенном выше коде определяется модуль с именем my_module.py, и с __all__установленным атрибутом при использовании будут импортированы только символы public_functionи. Имена функций и переменных, начинающиеся с подчеркивания, не будут импортированы.public_variablefrom my_module import *
Важно отметить несколько вещей. Если мы знаем абсолютные пути к функциям, начинающиеся с подчеркивания, мы все равно можем импортировать их в наш код. Однако это противоречит соглашению об инкапсуляции, поскольку подчеркивание ( _) обозначает их как частные члены модуля и указывает, что их не следует использовать вне модуля. Поэтому хорошей практикой является следовать соглашениям программирования Python, даже если Python не обеспечивает строгую инкапсуляцию.
Использование __all__атрибута в пакетах
Атрибут __all__также можно использовать в __init__.pyфайлах внутри пакета или подпакета для управления поведением по умолчанию при импорте подстановочных знаков для подмодулей или подпакетов. Это может помочь гарантировать, что при использовании импорта с подстановочными знаками в пакетах импортируются только определенные модули:
# my_package/__init__.py __all__ = ['submodule1', 'subpackage'] from . import submodule1 from . import subpackage
В этом примере показан файл, в котором указано, что он будет импортирован __init__.pyтолько при использовании. Другие подмодули или подпакеты не будут импортированы по умолчанию.submodule1subpackage1from my_package import *
Как и в случае с модулями, мы все равно можем импортировать другие модули, не указанные в списке __all__атрибутов, если мы знаем их абсолютные пути. Таким образом, __all__атрибут действует скорее как соглашение, а не как строгое правило. Он предназначен для сообщения о том, что можно публично использовать из модуля или пакета. Однако рекомендуется (import module_name)использовать явный импорт вместо импорта с подстановочными знаками (from module_name import *).
Стандартная библиотека Python и популярные сторонние пакеты
Стандартная библиотека Python — это набор модулей и пакетов, которые включены в установку интерпретатора Python. Эти модули предоставляют широкий спектр функциональных возможностей — от работы с типами данных и выполнения файловых операций до управления сетевыми взаимодействиями и реализации различных алгоритмов.
Некоторые из часто используемых модулей стандартной библиотеки Python включают:
- os: дает нам API для взаимодействия с операционной системой хоста
- math: предоставляет широкий спектр математических функций и констант (полезно при выполнении различных математических операций в нашем коде)
- datetime: позволяет нам работать с датами и временем в нашем коде
- json: позволяет нам обрабатывать данные JSON в нашем коде.
- argparse: позволяет нам создавать интерфейсы командной строки
- csv: позволяет нам читать и записывать файлы CSV
Стандартная библиотека содержит гораздо больше модулей, чем эти несколько примеров, каждый из которых имеет свою область применения, что обеспечивает преимущества разбиения кода на модули. Чтобы узнать больше о предлагаемых модулях, посетите официальную документацию Python.
Индекс пакетов Python и сторонние пакеты
Индекс пакетов Python (PyPI) — это репозиторий сторонних пакетов Python, которые расширяют функциональность стандартной библиотеки Python. Эти пакеты охватывают широкий спектр областей и предоставляют решения различных задач программирования. Эти пакеты созданы сообществом открытого исходного кода. Мы также можем создать свой собственный пакет и опубликовать его в репозитории.
Для управления сторонними пакетами Python использует инструмент под названием pip(Python Package Installer). pipпозволяет нам легко устанавливать, обновлять пакеты и управлять ими из PyPI.
Мы можем установить любую стороннюю библиотеку, используя pip:
pip install package_name
Например, чтобы установить Djangoпакет (который используется для веб-разработки), мы можем запустить это:
pip install django
Вот примеры некоторых популярных сторонних пакетов:
- NumPy : мощная библиотека для числовых вычислений на Python. Он обеспечивает поддержку больших многомерных массивов и матриц, а также множество математических функций для работы с этими массивами.
- Pandas : библиотека для манипулирования и анализа данных. Он предоставляет структуры данных, такие как DataFrames, для эффективной обработки и анализа табличных данных.
- Matplotlib : широко используемая библиотека для создания статических, анимированных и интерактивных визуализаций на Python. Он предлагает интерфейс, подобный MATLAB, для построения различных типов графиков и диаграмм.
- SciPy : построенный на основе NumPy, SciPy предоставляет дополнительные функции для оптимизации, интеграции, линейной алгебры, обработки сигналов и многого другого.
- Django : веб-фреймворк высокого уровня для создания веб-приложений. Он соответствует архитектуре Модель-Представление-Контроллер (MVC) и предлагает функции для обработки баз данных, URL-адресов, шаблонов и многого другого.
- Flask : еще один веб-фреймворк, Flask более легкий и минималистичный по сравнению с Django. Он идеально подходит для создания небольших веб-приложений или API.
- Requests : пакет для выполнения HTTP-запросов и обработки ответов. Это упрощает работу с веб-API и получение данных из Интернета.
Перечисленные выше пакеты — это лишь несколько примеров обширной экосистемы сторонних пакетов, доступных в PyPI. Подобные пакеты могут сэкономить нам много времени и усилий.
Упаковка и распространение
Упаковка и распространение наших проектов Python позволяет другим легко устанавливать и использовать наш код. Это особенно важно, когда мы хотим поделиться нашими библиотеками или приложениями с более широкой аудиторией. Вот краткий обзор того, как упаковывать и распространять наши проекты Python.
инструменты настройки для упаковки
setuptools— это пакет, который предоставляет возможности сборки и упаковки наших проектов Python. Это упрощает процесс создания дистрибутивов, включая исходные дистрибутивы ( sdist) и бинарные дистрибутивы ( bdist). Чтобы использовать setuptools, мы обычно создаем setup.pyскрипт в корневом каталоге нашего проекта.
Вот простой пример скрипта setup.py:
from setuptools import setup, find_packages setup( name="my_project", version="0.1", packages=find_packages(), install_requires=[ "requests", # other dependencies ], entry_points={ "console_scripts": [ "my_script = my_project.my_module:main", ], }, )
В приведенном выше скрипте мы указываем имя проекта, версию, пакеты, зависимости и любые точки входа, используя эту setup()функцию.
twine для публикации
Как только наш проект будет правильно упакован с помощью setuptools, мы сможем twineзагрузить наш пакет в PyPI для распространения. twine— это инструмент, который помогает нам безопасно загружать пакеты в PyPI.
Чтобы использовать twine, нам нужно установить его:
pip install twine
Затем мы идем в корневой каталог нашего проекта и используем следующую команду для загрузки нашего пакета:
twine upload dist/*
Имейте в виду, что для распространения пакетов через PyPI требуется создать учетную запись и следовать определенным правилам. Рекомендуется прочитать официальную документацию PyPI для получения подробных инструкций по упаковке и распространению.
Некоторые из рекомендаций:
- Версионирование. Правильно устанавливайте версии пакетов, чтобы указать изменения и обновления. Это помогает пользователям понять, что нового, и обеспечивает совместимость.
- Документация. Включите четкую документацию по коду, описывающую, как установить и использовать наш пакет. Используйте такие инструменты, как Sphinx, для создания документации.
- Лицензирование. Четко укажите лицензию, по которой распространяется пакет, чтобы пользователи понимали, как они могут его использовать.
- Тестирование. Проведите тестирование, чтобы убедиться, что пакет работает должным образом. Такие инструменты pytestмогут быть полезны для написания и запуска тестов.
Правильно упаковывая и распространяя наши проекты Python, мы облегчаем другим доступ и использование нашего кода, способствуя созданию более совместной среды разработки с открытым исходным кодом.
Заключение
В этом руководстве мы рассмотрели концепции модулей и пакетов в Python и их значение для написания хорошо организованного, поддерживаемого и многократно используемого кода.
Модули — это отдельные файлы, содержащие код Python, инкапсулирующий функции, классы и переменные. Они способствуют организации кода в рамках одного сценария и облегчают повторное использование кода в нескольких сценариях.
Пакеты выводят концепцию модульности на новый уровень, позволяя нам организовывать связанные модули в иерархии каталогов. Эта иерархическая структура улучшает организацию кода в более крупных проектах и способствует четкому разделению задач.
Продолжая изучение Python, овладение искусством модульного программирования с помощью модулей и пакетов, несомненно, поможет нам стать более опытными и эффективными разработчиками. Используя эти концепции, мы будем лучше подготовлены к решению сложных проектов и эффективному сотрудничеству с другими разработчиками.