Введение
В этом практическом занятии (лабораторной работе) вы научитесь различать модули и пакеты в Python, что является важным аспектом для эффективной организации и управления вашим кодом. В рамках практики (лабораторной работы) вы создадите пакет с именем my_package, содержащий файл __init__.py, и модуль с именем my_module.py.
Затем вы создадите скрипт main.py вне пакета для импорта и использования этого модуля, тем самым проиллюстрировав разницу между модулем (одиночным файлом, содержащим код Python) и пакетом (иерархией каталогов, содержащей модули и файл __init__.py). Эта практика (лабораторная работа) заложит основу для понимания того, как проверить, является ли модуль пакетом, используя атрибут __path__ и метод pkgutil.get_loader, которые будут рассмотрены в последующих шагах.
Различия между модулями и пакетами
В этом шаге вы научитесь различать модули и пакеты в Python. Понимание этой разницы является важным аспектом для эффективной организации и управления вашим кодом на Python.
Модули
Модуль представляет собой один файл (или несколько файлов), содержащий код на Python, например, определения функций, классов или переменных. Модули используются для организации кода в переиспользуемые блоки.
Пакеты
Пакет - это способ организации связанных модулей в иерархию каталогов. Пакет содержит один или несколько файлов модулей и специальный файл с именем __init__.py. Файл __init__.py может быть пустым, но его наличие указывает, что этот каталог должен быть восприниматься как пакет.
Создадим простой пример, чтобы проиллюстрировать разницу.
Сначала создайте каталог с именем
my_packageв каталоге~/project. Это будет наш каталог пакета.mkdir ~/project/my_packageПерейдите в каталог
my_package:cd ~/project/my_packageСоздайте пустой файл с именем
__init__.pyвнутри каталогаmy_package. Этот файл указывает, чтоmy_packageявляется пакетом Python.touch __init__.pyТеперь создайте файл с именем
my_module.pyвнутри каталогаmy_package. Это будет наш файл модуля.touch my_module.pyОткройте файл
my_module.pyв редакторе VS Code и добавьте следующий код:## my_module.py def greet(name): return f"Hello, {name}!"Сохраните файл
my_module.py.Теперь создадим скрипт Python вне каталога
my_package, чтобы использовать наш модуль. Вернитесь в каталог~/project:cd ~/projectСоздайте файл с именем
main.pyв каталоге~/project.touch main.pyОткройте файл
main.pyв редакторе VS Code и добавьте следующий код:## main.py import my_package.my_module result = my_package.my_module.greet("LabEx User") print(result)Сохраните файл
main.py.Запустите скрипт
main.py:python main.pyВы должны увидеть следующий вывод:
Hello, LabEx User!
Этот пример демонстрирует, как модуль (my_module.py) организован внутри пакета (my_package). Файл __init__.py необходим для того, чтобы Python распознал каталог как пакет.
Проверка наличия атрибута path
В этом шаге вы научитесь проверять наличие атрибута __path__ в пакетах Python. Атрибут __path__ является важным индикатором того, рассматривается ли каталог как пакет или как обычный каталог.
Атрибут __path__
Когда Python импортирует пакет, он ищет атрибут __path__. Если этот атрибут существует, Python рассматривает каталог как пакет и ищет подмодули и подпакеты по путям, указанным в __path__. Если атрибут __path__ отсутствует, Python рассматривает каталог как обычный.
Продолжим с примером my_package из предыдущего шага.
Перейдите в каталог
~/project:cd ~/projectСоздайте новый файл Python с именем
check_path.py:touch check_path.pyОткройте файл
check_path.pyв редакторе VS Code и добавьте следующий код:## check_path.py import my_package try: print(my_package.__path__) except AttributeError: print("my_package does not have __path__ attribute") import my_package.my_module try: print(my_package.my_module.__path__) except AttributeError: print("my_package.my_module does not have __path__ attribute")Сохраните файл
check_path.py.Запустите скрипт
check_path.py:python check_path.pyВы должны увидеть вывод, похожий на следующий:
['/home/labex/project/my_package'] my_package.my_module does not have __path__ attributeВывод показывает, что
my_packageимеет атрибут__path__, что подтверждает, что он рассматривается как пакет. С другой стороны,my_package.my_module(который является модулем) не имеет атрибута__path__.
Эта разница важна для понимания того, как Python организует и импортирует код. Пакеты используют __path__ для поддержки вложенных подмодулей и подпакетов, в то время как модули представляют отдельные файлы кода.
Использование pkgutil.get_loader
В этом шаге вы научитесь использовать функцию pkgutil.get_loader для получения загрузчика (loader) модуля или пакета. Загрузчики отвечают за загрузку модулей, и функция pkgutil.get_loader предоставляет удобный способ доступа к ним.
Что такое загрузчик (Loader)?
Загрузчик - это объект, который знает, как загрузить модуль. Он является частью механизма импорта в Python. Существуют различные типы загрузчиков для разных типов модулей (например, исходный код, скомпилированный код или расширения модулей).
Использование функции pkgutil.get_loader
Функция pkgutil.get_loader принимает в качестве входных данных имя модуля или пакета и возвращает объект загрузчика, если он найден. Если загрузчик не найден, функция возвращает None.
Продолжим с примером my_package из предыдущих шагов.
Перейдите в каталог
~/project:cd ~/projectСоздайте новый файл Python с именем
get_loader_example.py:touch get_loader_example.pyОткройте файл
get_loader_example.pyв редакторе VS Code и добавьте следующий код:## get_loader_example.py import pkgutil loader = pkgutil.get_loader("my_package.my_module") if loader is not None: print(f"Loader found for my_package.my_module: {loader}") else: print("No loader found for my_package.my_module") loader = pkgutil.get_loader("os") if loader is not None: print(f"Loader found for os: {loader}") else: print("No loader found for os") loader = pkgutil.get_loader("nonexistent_module") if loader is not None: print(f"Loader found for nonexistent_module: {loader}") else: print("No loader found for nonexistent_module")Сохраните файл
get_loader_example.py.Запустите скрипт
get_loader_example.py:python get_loader_example.pyВы должны увидеть вывод, похожий на следующий:
Loader found for my_package.my_module: <_frozen_importlib_external.SourceFileLoader object at 0x...> Loader found for os: <_frozen_importlib_external.SourceFileLoader object at 0x...> No loader found for nonexistent_moduleВывод показывает, что загрузчик был найден для
my_package.my_moduleи встроенного модуляos, но не был найден дляnonexistent_module.
Этот пример демонстрирует, как использовать функцию pkgutil.get_loader для проверки, может ли быть загружен модуль или пакет, и для получения его объекта загрузчика. Это может быть полезно для интроспекции и динамической загрузки модулей.
Резюме
В этом практическом занятии (лабораторной работе) вы научились различать модули и пакеты Python. Модуль представляет собой отдельный файл, содержащий код на Python, в то время как пакет - это иерархия каталогов, содержащая модули и файл __init__.py, который обозначает каталог как пакет.
Вы создали пакет с именем my_package с файлом __init__.py и модуль с именем my_module.py, содержащий функцию greet. Затем вы создали скрипт main.py вне пакета для импорта и использования функции greet из модуля my_module в пакете my_package.



