Получи случайную криптовалюту за регистрацию!

Переменные окружения и dotenv Когда мы пишем какие-то сервисы | Советы разработчикам (python и не только)

Переменные окружения и dotenv

Когда мы пишем какие-то сервисы (веб-приложения, боты, обработчики задач), им бывает необходимо передать какие-то настройки. Частыми вариантами будут: реквизиты для доступа к базе данных, токен для сторонних API и т.д.

В общем случае у нас есть два стандартных варианта передачи настроек:
* файлы конфигурации
* переменные окружения

Файлы конфигурации удобны, когда настроек много и они имеют сложную структуру. Но при запуске сервиса в некоторых окружениях, таких как AWS Lambda, Kubernetes и Heroku доставка таких файлов с настройками до работающего экземпляра приложения может быть нетривиальна.
В противовес этому, во многих случаях такие сервисы позволяют через свои способы настройки указать переменные окружения, с которыми будет запущен процесс. Да, мы не сможем передать в этом случае сложные иерархические структуры, но зачастую это не нужно.

Переменные окружения задаются как правило при старте процесса вызывающей его стороной или наследуются от родительского процесса. Так же можем менять их для своего процесса в процессе его работы, но скорее всего это будет неожиданно, так как многие настройки считываются при старте.

Чтобы передать переменные окружения нашему приложению, мы можем:
* При использовании bash/sh/zsh сделать export этих переменных или указать их перед командой которую мы выполняем
* Так же для bash удобно подготовить один или несколько файлов с инструкциями export и применять их с помощью команды source
* При запуске через Pycharm переменные окружения можно задать в настройках конфигурации запуска. Иногда удобно иметь несколько таких конфигураций, чтобы отлаживать софт с разными настройками. Другие IDE имеют аналогичные возможности.
* Так же вы всегда можете задать переменные окружения глобально средствами вашей ОС. Но тогда для смены их возможно придется перезайти в учетную запись.
* При запуске сервиса через systemd вы можете указать переменные окружения прямо в service файле или указать из какого файла их необходимо прочитать
* При запуске через docker так же они указываются в команде запуска контейнера docker run напрямую или через --env-file. В случае`docker-compose` эти возможности сохраняются

Стоит отметить относительную популярность библиотек типа python-dotenv. Они позволяют во время работы приложения прочитать конфигурационный файл своего формата и поменять переменные окружения текущего процесса согласно этому файлу. Опасность этого подхода в том, что в момент загрузки этого файла приложение уже работает и при наличии других архитектурных проблем эти значения могут конфликтовать с уже инициализированными объектами, что потребует дополнительных усилий для поддержания работоспособности кода. Некоторые реализации библиотек для чтения .env-файлов могут искать файлы не только в текущем каталоге, но и вверх в каждом родительском каталоге, что может приводить к непредсказуемому поведению кода.

Хочу также обратить внимание, что хотя формат конфига python-dotenv похож на используемый docker, systemd или bash файл, эти все форматы не совместимы. Где-то вы можете ставить пробелы около знака =, где-то допустимо или требуется писать export, где-то невозможно задать многострочные значения и т.д.


Дополнительные материалы:
* https://12factor.net/
* https://www.freedesktop.org/software/systemd/man/systemd.exec.html
* https://docs.docker.com/compose/env-file/
* https://ru.wikipedia.org/wiki/Переменная_среды