k06. Mодули, пакеты, venv и pip.
UAV Python Pro · Конспект K06 · Модуль M1. Python intensive: модули, пакеты, venv и pip · Редакция 1.1 · После CHECKPOINT-K05
На занятии K05 вы научились собирать логику программы в функции. Когда функций становится много, все их невозможно хранить в одном файле: такой проект перестаёт быть читаемым. На этом занятии вы разберёте, каким образом Python раскладывает код по файлам и папкам, как подключать собственный код с помощью оператора import, для чего необходимо виртуальное окружение venv, которое вы уже создали на занятии K01, и как аккуратно устанавливать библиотеки с помощью инструмента pip. Это материал является непосредственной подготовкой к установке библиотеки pymavlink и других инструментов курса. Практические задания выполняются в виртуальном окружении проекта K01; соответствующие файлы расположены в каталоге code/M01_python/k06_*.py.
Главная мысль занятия состоит в следующем: один файл должен соответствовать одному понятному фрагменту ответственности. Готовый чужой код подключается как библиотека с помощью инструмента pip в виртуальное окружение, тогда как собственный код подключается с помощью оператора import. Команда python -m pip устанавливает пакеты именно в тот интерпретатор Python, которым вы пользуетесь в данный момент. Файл зависимостей, который называется requirements, необходим для того, чтобы через месяц или на устройстве Raspberry Pi можно было воспроизвести тот же самый набор библиотек.
code/M01_python/k06_task1_import_units.py и соседние файлы, имена которых начинаются с префикса k06_.Содержание
1. Цели урока
По завершении этого занятия вы будете обладать следующими умениями.
- Вы сможете объяснить, чем модуль отличается от пакета.
- Вы научитесь импортировать собственный учебный модуль с помощью оператора
importи конструкцииfrom … import. - Вы научитесь использовать конструкцию
if __name__ == "__main__"и объяснять, для чего она предназначена. - Вы научитесь проверять, что инструмент
pipустанавливает пакеты в активное виртуальное окружение, а не в посторонний интерпретатор Python. - Вы научитесь выполнять команду
python -m pip freezeи понимать смысл файла зависимостей. - Вы сможете описать словами структуру папок учебного проекта курса.
- Вы научитесь воздерживаться от установки библиотек в системный интерпретатор Python только потому, что такой способ кажется более быстрым.
import и pip проект, который «работает дома», может перестать работать на борту аппарата.2. Словарь урока
| Термин | Объяснение простыми словами |
|---|---|
| Модуль | Один файл с расширением .py, из которого можно импортировать функции и переменные. |
| Пакет | Папка, в которой содержатся модули обычно вместе с файлом __init__.py; оператор import воспринимает такую папку как единое пространство имён. |
| import | Команда, которая подключает модуль или пакет, чтобы можно было пользоваться его содержимым. |
| venv | Виртуальное окружение — отдельный изолированный интерпретатор Python со своим набором установленных пакетов для данного проекта. |
| pip | Программа, которая устанавливает и обновляет пакеты Python. |
| PyPI | Каталог готовых пакетов, который расположен в интернете и из которого инструмент pip обычно загружает пакеты. |
| requirements.txt | Текстовый файл, который содержит список зависимостей проекта, то есть перечень необходимых пакетов. |
| dependency / зависимость | Внешняя библиотека, без которой код не сможет запуститься. |
| __name__ | Специальная переменная Python, значение которой показывает, был ли файл запущен как программа или был импортирован как модуль. |
3. Зачем делить код на файлы
Пока размер кода составляет от тридцати до пятидесяти строк, хранение всего кода в одном файле является допустимым. Когда же в проекте появляются такие задачи, как разбор телеметрии, построение миссии, запись журналов, связь по протоколу MAVLink и обработка данных с камеры, единственный файл превращается в беспорядочный набор инструкций.
Разделение кода по файлам даёт следующие преимущества.
- Появляются понятные границы между частями программы: один файл содержит только функции перевода единиц измерения, другой файл содержит только печать отчёта.
- Появляется возможность повторного использования кода: одну функцию можно импортировать из двух различных скриптов.
- Упрощается тестирование кода и чтение изменений, которые показывает система контроля версий Git.
kNN_task*.py, могут оставаться точками входа в программу. Общую логику, которую вы собираетесь использовать многократно, следует выносить в модули, расположенные внутри пакета.4. Модуль и пакет
Что такое модуль
Модуль в языке Python представляет собой, по существу, один файл с расширением .py. Когда вы записываете оператор import, интерпретатор Python загружает этот файл и делает его функции доступными для использования.
Примером из практики занятия служит файл units.py, который находится внутри учебного пакета и является модулем с функциями перевода единиц измерения.
# фрагмент sensors/units.py (полный файл находится в материалах)
def alt_cm_to_m(alt_cm: int) -> float:
"""Сантиметры → метры."""
return alt_cm / 100.0
Что такое пакет
Пакет представляет собой папку, в которой расположены модули и которую интерпретатор Python может импортировать как единое пространство имён. Обычно в такой папке присутствует файл __init__.py, который может быть и пустым. Именно этот файл помечает папку как пакет.
Учебная структура, которая используется на занятии K06, выглядит следующим образом:
code/M01_python/k06_demo_package/
sensors/
__init__.py
units.py
В этой структуре папка sensors является пакетом, а файл units.py является модулем, который расположен внутри данного пакета.
import соответствует действию «открыть нужный документ из нужной папки».5. Оператор import и конструкция from … import
import — это команда, которая подключает модуль или пакет. После выполнения импорта вы можете вызывать функции либо через имя модуля, либо импортировать отдельные имена напрямую.
Рассмотрим два часто используемых способа записи.
# Способ 1: импорт модуля целиком, вызов функции через имя модуля
import math
print(math.sqrt(9))
# Способ 2: импорт конкретных имён из модуля
from math import sqrt
print(sqrt(9))
Для учебного пакета sensors, который рассматривается в задании k06_task1, применяется следующая запись:
# После настройки sys.path (в учебном файле задания это выполнено явно)
from sensors.units import alt_cm_to_m, voltage_label
print(alt_cm_to_m(2500))
print(voltage_label(15.556))
6. Конструкция if __name__ == "__main__"
У каждого файла Python имеется специальная переменная __name__. Её значение зависит от того, каким способом был запущен данный файл.
- Если файл был запущен напрямую, то есть командой
Runв среде PyCharm или командойpython file.py, то переменная__name__принимает значение"__main__". - Если файл был импортирован из другого файла, то переменная
__name__принимает значение имени этого модуля, а не строку"__main__".
Именно поэтому применяется так называемая «охрана main», то есть проверка точки входа:
def greet(name: str) -> str:
return f"hello, {name}"
def main() -> None:
# Код, который нужен только при запуске файла как программы
print(greet("uav-dev"))
if __name__ == "__main__":
main()
k06_task2_main_guard.py необходимо запустить напрямую; при этом на экране появится приветствие. Проверку поведения при импорте этого файла как модуля можно выполнить позже, когда работа с пакетами станет более привычной.7. Виртуальное окружение venv и инструмент pip
venv — напоминание
venv, то есть виртуальное окружение, представляет собой отдельную изолированную среду Python для проекта: у неё собственный интерпретатор и собственный набор установленных пакетов. На занятии K01 вы уже создали такое окружение в среде PyCharm. Здесь мы закрепляем смысл этого понятия.
Виртуальное окружение необходимо по следующим причинам.
- Проект A может использовать одну версию библиотеки pymavlink, а проект B — другую версию этой библиотеки.
- Системный интерпретатор Python в операционной системе Windows не загрязняется лишними пакетами.
- На устройстве Raspberry Pi упрощается воспроизведение того же самого окружения.
Проверить, что вы работаете в виртуальном окружении проекта, можно следующим образом:
import sys
print(sys.executable)
# В пути должно присутствовать нечто вроде ...\.venv\Scripts\python.exe
Инструмент pip — установка пакетов
pip — это стандартная программа установки пакетов Python. Пакеты, как правило, располагаются в каталоге PyPI, то есть в индексе пакетов Python, который находится в интернете.
Правильная форма команды для этого курса выглядит так:
python -m pip install имя_пакета
Разберём эту команду по частям.
python— это тот интерпретатор, который является активным в данный момент (желательно, чтобы это был интерпретатор из виртуального окружения);-m pip— означает «запусти модуль pip именно этим интерпретатором python»;- благодаря такой форме снижается вероятность того, что сработает посторонний инструмент pip, который принадлежит другому интерпретатору Python и был найден в переменной PATH.
# Обновить сам инструмент pip внутри виртуального окружения (безопасно и полезно)
python -m pip install -U pip
# Посмотреть, какие пакеты уже установлены
python -m pip list
Файл requirements и команда freeze
requirements.txt — это текстовый файл, который содержит список зависимостей проекта, то есть перечень необходимых пакетов, часто с указанием номеров версий.
Команда freeze выводит на экран фактически установленные пакеты текущего окружения:
python -m pip freeze
Снимок установленных пакетов можно сохранить в файл (это действие носит учебный характер):
python -m pip freeze > requirements-lock-demo.txt
requirements.txt, который содержит основные пакеты курса. Второй уровень — «строгий снимок», который создаёт команда freeze и который служит для точного воспроизведения версий пакетов. В модуле M1 достаточно понять назначение обеих команд. Позднее мы зафиксируем рабочий файл requirements.txt для библиотеки pymavlink.k06_task3_pip_freeze_note.py лишь напоминает о необходимых шагах. Команды для инструмента pip вы должны выполнить самостоятельно в терминале виртуального окружения и изучить результат выполнения команды freeze.8. Структура проекта курса (как поддерживать порядок)
uav-python-pro/ ← корень репозитория Git и проекта PyCharm
.venv/ ← виртуальное окружение (не сохраняется в репозиторий)
.gitignore
code/
M01_python/
k03_*.py … k06_*.py ← точки входа и практические задания
k06_demo_package/
sensors/
__init__.py
units.py ← переиспользуемый модуль
docs/ ← ваши заметки (по желанию)
mavlink_helpers, mission_builder и другие.9. Типичные ошибки
| Ошибка | Что вы наблюдаете | Как следует рассуждать |
|---|---|---|
| Ошибка ModuleNotFoundError | Интерпретатор Python не находит модуль или пакет | Проверьте имя модуля, расположение папки, переменную sys.path и то, что запуск выполняется из ожидаемого каталога |
| Инструмент pip установил пакет «не туда» | Оператор import в среде PyCharm не видит установленный пакет | Проверьте значение sys.executable; всегда используйте команду python -m pip |
| Работа без виртуального окружения | Возникают конфликты версий, поведение отличается от ожидаемого | Вернитесь к интерпретатору из каталога .venv в настройках PyCharm |
| Код на верхнем уровне модуля отправляет команды при импорте | Побочные эффекты возникают при импорте из другого файла | Скрывайте запуск за конструкцией if __name__ == "__main__" |
| Применение конструкции from x import * | Непонятно происхождение имён в коде | Импортируйте имена явно |
10. Практика
Задача 6.1. Импорт собственного модуля
Файл k06_task1_import_units.py и пакет k06_demo_package/sensors. Запустите задачу task1 и получите значение 25.0 и строку с напряжением.
Задача 6.2. Охрана main
Файл k06_task2_main_guard.py. Запустите его напрямую. Убедитесь, что вы понимаете: при импорте этого файла функция main не должна вызываться сама по себе.
Задача 6.3. Команда pip freeze в виртуальном окружении
В терминале виртуального окружения выполните команды python -m pip install -U pip и python -m pip freeze. При желании сохраните результат команды freeze в файл. Случайные пакеты не устанавливайте.
Задача 6.4. Запись изменений в репозиторий
git add code/M01_python/k06_*.py code/M01_python/k06_demo_package
git commit -m "K06: modules package import main guard pip freeze"
11. Проверьте себя
- Чем модуль отличается от пакета? Приведите пример из структуры k06_demo_package.
- Для чего нужен файл __init__.py в учебном пакете?
- Чем запись import math отличается от записи from math import sqrt?
- Что означает конструкция if __name__ == "__main__"? Что произойдёт, если убрать эту проверку и оставить код запуска, который выполняется при импорте?
- Почему мы записываем команду python -m pip, а не просто pip?
- Зачем необходимо виртуальное окружение, если «и так всё устанавливается»?
- Что выводит на экран команда pip freeze?
- Почему не следует устанавливать пакеты в системный интерпретатор Python «на авось»?
12. Чек-лист самопроверки
- Я объясняю своими словами, что такое модуль и что такое пакет.
- Я запустил задачу k06_task1 и увидел ожидаемый результат.
- Я понимаю смысл конструкции if __name__ == "__main__".
- Значение sys.executable указывает на каталог .venv проекта.
- Я умею выполнять команды python -m pip list и python -m pip freeze.
- Я не устанавливаю пакеты за пределами виртуального окружения.
- Я понимаю, для чего в будущем понадобится файл requirements.
- Я записал изменения по занятию K06 в репозиторий с помощью git.
13. Что дальше
- Предыдущее занятие: K05 · Циклы и функции.
- Текущее занятие: K06 · Модули, пакеты, venv, pip.
- Следующее занятие: K07 · Файлы и форматы данных.
- Горизонт модуля M1: занятие K12 «CLI Fake GCS» и контрольный рубеж G1.
docs/05_EDITOR_STYLE_GUIDE.md, правило R13.