Для решения вышеперечисленных задач используется подход, основанный на построении виртуальных окружений Python – своего рода песочниц, внутри которых изолированно запускается приложение со своими библиотеками. При этом если данное приложение обновляет и изменяет данные библиотеки, это никак не затрагивает другие приложения с такими же библиотеками-зависимостями. Таким образом, виртуальное окружение в Python — способ изолировать зависимости (пакеты) для определённого проекта.При создании приложений на Python могут возникнуть несколько проблем, которые связаны с использованием библиотек разных версий. Например:Разные проекты используют одни и те же библиотеки, но при этом версии библиотек отличаются.
Возможна ситуация, когда для корректной работы приложения необходимо зафиксировать версию одной из библиотек-зависимостей. Очевидно, что в данной ситуации пользоваться глобальным хранилищем библиотек будет неуместным, так как это может повлечь за собой цепочку проблем.
У приложения может не быть доступа к каталогу глобального хранилища пакетов.
Виртуальные окружения Python
Каков алгоритм работы с виртуальным пространством?
1. Создать ВП
2. Активировать ВП
3. Внести изменения(например, установить новый модуль)
4. Деактивировать ВП
А теперь подробнее.
1. Как создать виртуальное окружение?
Существует достаточно много модулей, которые позволяют создавать виртуальные окружения в Python. Некоторые уже входят в стандартную библиотеку(venv), другие необходимо установить из каталога PyPI(virtualenv, pyenv).
Создать виртуальную среду с помощью выбранной утилиты можно по-разному, в зависимости от того, где вы работаете с кодом:
- Можно создать виртуальное окружение в консоли. Например, в случае стандартного модуля venv это будет выглядеть следующим образом: python3 -m venv /path/to/new/virtual/environment
- Если вы работаете с IDE(например, PyCharm) при создании проекта необходимо выбрать соответствующую опцию по созданию виртуального пространства. Обратите внимание, что в зависимости от уже установленных библиотек, в выпадающем списке могут быть доступны несколько вариантов модулей, создающих виртуальные среды:
Создание виртуального пространства проекта в PyCharm
В результате создается директория с говорящим названием venv, которая содержит все файлы, необходимые для поддержания и корректного функционирования свежесозданной виртуальной среды. Содержимое данного каталога на Linux выглядит приблизительно так:
Директория venv
├── bin
│ ├── activate
│ ├── activate.csh
│ ├── activate.fish
│ ├── easy_install
│ ├── easy_install-3.5 │ ├── pip
│ ├── pip3
│ ├── pip3.8 │ ├── python -> python3.8 │ ├── python3 -> python3.8 │ └── python3.8 -> /Library/Frameworks/Python.framework/Versions/3.8/bin/python3.8 ├── include
├── lib
│ └── python3.8 │ └── site-packages
└── pyvenv.cfg
2. Как активировать виртуальную среду?
Итак, вы создали виртуальное пространство для вашего проекта и хотите им воспользоваться. Для этого необходимо его активировать. Процесс активации среды немного различается в зависимости от типа операционной системы:В ОС Windows структура директории venv выглядит схожим образом.
Что находится в этих директориях?bin – файлы, обеспечивающие взаимодействие с виртуальной средой;
include – С-заголовки, компилирующие пакеты Python;
lib – копия глобальной версии Python вместе с папкой site-packages, в которой установлены библиотеки для общего пространства
Консоль
# Для Linux # Используем команду source и передаем ей скрипт activate из папки bin $ source my_project/venv/bin/activate
# Для Windows # Запускаем bat-файл activate.bat > D:\home\python\project\env\Scripts\activate.bat
3. Работа внутри виртуальной среды
Теперь с помощью одного из менеджеров пакетов(pip или easy_install) можно просматривать/устанавливать/изменять/удалять пакеты. Несколько примеров с использованием менеджера pip:
Консоль
# Список установленных библиотек $ pip3 list
Package Version
------------------ --------
certifi 2019.3.9
pip 19.3.1
pytest 5.4.2
requests 2.22.0
selenium 3.141.0
setuptools 41.6.0
six 1.12.0
urllib3 1.25.2
# Установка библиотеки requests $ pip3 install requests
# Удаление библиотеки six $ pip3 uninstall six
4. Как деактивировать виртуальную среду?
После того, как вы завершили работу с текущей средой, необходимо ее деактивировать. Процесс так же немного отличается на разных типах ОС:
Консоль
# Для Linux # В рамках текущей сессии вызываем команду deactivate (venv) $ deactivate
# Для Windows # Запускаем bat-файл deactivate.bat > D:\home\python\project\env\Scripts\deactivate.bat
ПРАКТИЧЕСКИЙ БЛОК
Исполняемая часть модуля. Переменная __name__.
При написании модуля необходимо заранее продумать, будет он запускаться самостоятельно, или он предназначен для импорта в другие модули. Почему это важно? Потому что, как мы писали выше, при импорте исполняемая часть кода будет выполнена интерпретатором.
Рассмотрим пример. Перед нами модуль calculator, который содержит две функции(sum_up() для сложения и sub() для вычитания) и исполняемую часть(тесты функций модуля):Модуль в Python можно использовать следующим образом:Запустить автономно. Модуль - это скрипт на Python, а значит, его можно запустить в терминале/консоли или через IDE.
Импортировать. При этом, как мы уже рассмотрели выше, используется инструкция import.
calculator.py
# Функции def sum_up(a, b): return a + b
def sub(a, b): return a - b
# Исполняемый код print('Сумма: ', sum_up(2, 3))
print('Разность: ', sub(5, 1))
Если мы запустим модуль calculator самостоятельно, то будет выполнена исполняемая часть. Вывод в консоль:
Терминал
$ python3 calculator.py
Сумма: 5 Разность: 4
А что произойдет с исполняемой частью, если мы импортируем модуль calculator внутрь другого модуля? Ответ - то же самое! Она также будет выполнена интерпретатором. Нужно ли это во время импорта? В подавляющем большинстве случаев - нет.
Как этого избежать? Как сделать так, чтобы при автономном запуске скрипта исполняемая часть выполнялась, а при импорте - нет? Ответ следующий: достаточно использовать специальный атрибут модуля __name__, который меняет свое значение в зависимости от того, запущен модуль или импортирован:
- Атрибут __name__ содержит имя модуля, если он был импортирован (например, "calculator" или "math")
- Атрибут __name__ принимает значение "__main__", если модуль был запущен автономно.
Проверка значения атрибута __name__
Соответственно для решения проблемы поступают следующим образом:
- Вспомогательные модули(т. е. те модули, которые планируется импортировать) избавляются от кода вне функций и/или класов.
- В основном файле программы(тот модуль, который планируется запускать) вставляется проверка атрибута __name__. Выглядит эта проверка следующим образом(наверняка, вы уже видели ее не раз, но не заостряли внимание, как это работает):
Python
# Классы/ функции модуля # <..>
if __name__ == '__main__':
# Исполняемая часть # <..>
При наличии такой проверки если этот файл будет импортирован, его исполняемый код не будет выполняться интерпретатором Python.