dotenv Python
| Введение | |
| Простой пример | |
| dotenv_values | |
| .env.secret | |
| Импорт | |
| Похожие статьи |
Введение
Процитирую сайт https://12factor.net/ru/config
Сохраняйте конфигурацию в среде выполнения
Конфигурация приложения – это всё, что может меняться между развёртываниями (среда разработки, промежуточное и рабочее развёртывание). Это включает в себя:
- Идентификаторы подключения к ресурсам типа базы данных, кэш-памяти и другим сторонним службам
- Регистрационные данные для подключения к внешним сервисам, например, к Amazon S3 или Twitter
- Значения зависимые от среды развёртывания такие, как каноническое имя хоста
Иногда приложения хранят конфигурации как константы в коде. Это нарушение методологии двенадцати факторов, которая требует строгого разделения конфигурации и кода. Конфигурация может существенно различаться между развёртываниями, код не должен различаться.
Лакмусовой бумажкой того, правильно ли разделены конфигурация и код приложения, является факт того, что кодовая база приложения может быть в любой момент открыта в свободный доступ без компрометации каких-либо приватных данных.
Обратите внимание, что это определение “конфигурации” не включает внутренние конфигурации приложения, например такие как ‘config/routes.rb’ в Rails, или того как основные модули будут связаны в Spring. Этот тип конфигурации не меняется между развёртываниями и поэтому лучше всего держать его в коде.
Другим подходом к конфигурации является использование конфигурационных файлов, которые не сохраняются в систему контроля версия, например ‘config/database.yml’ в Rails. Это огромное улучшение перед использованием констант, которые сохраняются в коде, но по-прежнему и у этого метода есть недостатки: легко по ошибке сохранить конфигурационный файл в репозиторий; существует тенденция когда конфигурационные файлы разбросаны в разных местах и в разных форматах, из за этого становится трудно просматривать и управлять всеми настройками в одном месте. Кроме того форматы этих файлов, как правило, специфичны для конкретного языка или фреймворка.
Приложение двенадцати факторов хранит конфигурацию в переменных окружения (часто сокращается до env vars или env). Переменные окружения легко изменить между развёртываниями, не изменяя код; в отличие от файлов конфигурации, менее вероятно случайно сохранить их в репозиторий кода; и в отличие от пользовательских конфигурационных файлов или других механизмов конфигурации, таких как Java System Properties, они являются независимым от языка и операционной системы стандартом.
Другим подходом к управлению конфигурациями является группировка. Иногда приложения группируют конфигурации в именованные группы (часто называемые “окружениями”) названые по названию конкретного развёртывания, например как development, test и production окружения в Rails. Этот метод не является достаточно масштабируемым: чем больше различных развёртываний приложения создаётся, тем больше новых имён окружений необходимо, например staging и qa. При дальнейшем росте проекта, разработчики могут добавлять свои собственные специальные окружения, такие как joes-staging, в результате происходит комбинаторный взрыв конфигураций, который делает управление развёртываниями приложения очень хрупким.
В приложении двенадцати факторов переменные окружения являются не связанными между собой средствами управления, где каждая переменная окружения полностью независима от других. Они никогда не группируются вместе в “окружения”, а вместо этого управляются независимо для каждого развёртывания. Эта модель которая масштабируется постепенно вместе с естественным появлением большего количества развёртываний приложения за время его жизни.
Установка
python -m pip install python-dotenv
Collecting python-dotenv Downloading python_dotenv-1.0.1-py3-none-any.whl.metadata (23 kB) Downloading python_dotenv-1.0.1-py3-none-any.whl (19 kB) Installing collected packages: python-dotenv Successfully installed python-dotenv-1.0.1
Простой пример
Создадим файл .env рядом со скриптом dotenv_ex.py
# .env POSTGRES_USER=tester HOST=127.0.0.1 PORT=5432 ENDPOINT=${HOST}:${PORT}
# dotenv_ex.py import os from dotenv import load_dotenv load_dotenv() print(os.getenv('POSTGRES_USER')) print(os.getenv('ENDPOINT'))
python dotenv_ex.py
tester
127.0.0.1:5432
dotenv_values
Тот же самый результат можно получить используя dotenv_values
# dotenv_ex.py from dotenv import dotenv_values config = dotenv_values(".env") print(config["POSTGRES_USER"]) print(config["ENDPOINT"])
Тип возвращаемого dotenv_values() значения - <class 'collections.OrderedDict'>
.env.secret
Вместо одного файла .env создадим два .env.secret и .env.shared
# .env.secret TELEGRAM=aofeed
# .env.shared HOST=testsetup.ru PORT=80 ENDPOINT=${HOST}:${PORT}
# dotenv_ex.py from dotenv import dotenv_values config = { **dotenv_values(".env.secret"), **dotenv_values(".env.shared") } print(config)
python dotenv_ex.py
{'TELEGRAM': 'aofeed', 'HOST': 'testsetup.ru', 'PORT': '80', 'ENDPOINT': 'testsetup.ru:80'}
Импорт
Рассмотрим функцию get_url()
# dotenv_ex.py from dotenv import dotenv_values def get_url() -> str: config = { **dotenv_values(".env.secret"), **dotenv_values(".env.shared") } return config["ENDPOINT"] if __name__ == "__main__": print(get_url())
python dotenv.py
testsetup.ru:80
Если теперь импортировать модуль dotenv_ex.py из другой директории и вызвать функцию get_url() ничего не получится.
dotenv_demo/ |-- configs | |-- .env.secret | |-- .env.shared | `-- dotenv_ex.py |-- src | `-- main.py
from dotenv_demo.configs import dotenv_ex print(dotenv_ex.get_url())
python main.py
Traceback (most recent call last): File "C:\Users\A\dotenv_demo\src\main.py", line 4, in <module> print(dotenv_ex.get_url()) ^^^^^^^^^^^^^^^^^^^ File "C:\Users\A\dotenv_demo\configs\dotenv_ex.py", line 11, in get_url return config["ENDPOINT"] ~~~~~~^^^^^^^^^^^^ KeyError: 'ENDPOINT'
Интерпретатор будет искать .env.secret и .env.shared файлы в директории src и не сможет их найти.
Чтобы явно указать путь до нужных файлов, воспользуемся os.path.join()
# dotenv_ex.py import os from dotenv import dotenv_values def get_url() -> str: path_to_secret = os.path.join(os.path.dirname(__file__), ".env.secret") path_to_shared = os.path.join(os.path.dirname(__file__), ".env.shared") config = { **dotenv_values(path_to_secret), **dotenv_values(path_to_shared) } return config["ENDPOINT"] if __name__ == "__main__": print(get_url())
python main.py
testsetup.ru:80
Автор статьи: Андрей Олегович
| Основы Python | |
| Type Hints | |
| __future__ | |
| configparser | |
| Менеджер контекста | |
| docstring | |
| #!: Shebang | |
| Объекты | |
| Итерация | |
| os | |
| pathlib | |
| flake8 |