Переменные окружения для Python проектов

в 9:12, , рубрики: bash, direnv, dotenv, python

Переменные окружения для Python проектов

При разработки web-приложения или бота мы часто имеем дело с какой-либо секретной информацией, различными токенами и паролями (API-ключами, секретами веб-форм). "Хардкодить" эту информацию, а тем более сохранять в публично доступной системе контроля версий это очень плохая идея.

# Плохая практика. Не делай так.
API_KEY = 'very_secret_password'

Конфигурационные файлы

Самый простой путь решения данной проблемы, это создание отдельного конфигурационного файла со всей чувствительной информацией и добавление его в .gitignore. Минус такого подхода в том, что в гит нужно держать ещё и шаблон конфигурационного файла и не забывать его периодически обновлять.

# Уже лучше.
from config import API_KEY
app = Flask(__name__)
app.config['API_KEY'] = API_KEY

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

Более продвинутый подход, это использование переменных окружения. Переменные окружения это именованные переменные, содержащие текстовую информацию, которую могут использовать запускаемые программы. Например, чтобы запустить flask-приложение, вначале нужно указать в переменной окружения FLASK_APP имя нашего приложения:

$ export FLASK_APP=hello.py
$ flask run
 * Running on http://127.0.0.1:5000/

С помощью переменных окружения можно получать различные параметры приложение и секретные ключи:

import os
app.config['API_KEY'] = os.environ.get('API_KEY')

Библиотека python-dotenv

Чтобы не задавать каждый раз вручную переменные окружения при новом запуске терминала, можно воспользоваться пакетом python-dotenv. Он позволяет загружать переменные окружения из файла .env в корневом каталоге приложения.
Устанавливаем пакет:

pip install python-dotenv

Теперь можно создать файл .env со всеми переменными среды, которые необходимы вашему приложению. Важно, добавьте .env-файл в .gitignore, не храните его в системе контроля версий.

import os
from dotenv import load_dotenv
dotenv_path = os.path.join(os.path.dirname(__file__), '.env')
if os.path.exists(dotenv_path):
    load_dotenv(dotenv_path)

Этот .env-файл можно использовать для всех переменных конфигурации, но его нельзя использовать для переменных среды FLASK_APP и FLASK_DEBUG, так как они необходимы уже в процессе начальной загрузки приложения.

Утилита direnv

Переменные среды могут быть автоматически загружены при входе в папку с проектом, это особенно удобно при работе с несколькими проектами одновременно. Сделать это позволяет утилита direnv. Direnv — это менеджер переменных среды для терминала, поддерживает bash, zsh, tcsh и др. оболочки. Позволяет автоматически загружать и выгружать переменные среды в зависимости от вашего текущего каталога. Это позволяет иметь переменные среды, специфичные для каждого проекта. Перед каждым приглашением проверяется наличие файла .envrc в текущем и родительском каталогах. Если файл существует, он загружается в подшаблон bash, и все экспортированные переменные затем захватываются direnv, а затем становятся доступными для оболочки.

Установка direnv

sudo apt-get install direnv

Далее необходимо в нести изменения для настройки нашей оболочки, для bash необходимо в конец файла ~/.bashrc добавить следующее и перезапустить консоль:

eval "$(direnv hook bash)"

Пример использования direnv

Создадим новую папку для проекта:

$ mkdir ~/my-project
$ cd ~/my-project

Покажем, что переменная окружения FLASK_APP не загружена:

$ echo $FLASK_APP
nope

Запишем переменные окружения в файл .envrc:

$ echo export FLASK_APP=hello.py > .envrc
.envrc is not allowed

Для обеспечения безопасности, после создания или изменения файла .envrc, нужно выполнить подтверждение с помощью команды direnv allow:

$ direnv allow .
direnv: reloading
direnv: loading .envrc
direnv export: +FLASK_APP

Покажем, что переменная окружения загружена:

$ echo $FLASK_APP
hello.py

При выхода из папки с проектом переменные окружения выгружаются

$ cd ..
direnv: unloading

и становятся снова не заданными

$ echo $FLASK_APP
nope

Работа с виртуальным окружением в direnv

Кроме загрузки переменных окружения, утилита direnv позволяет также работать с виртуальным окружением для Python.
Виртуальное окружение позволяет использовать для отдельные проектов разные версии интерпретатора python и пакетов библиотек. Существует несколько способов создания виртуального окружения для python, здесь мы рассмотрим модуль venv, для другие варианты описаны в документации к direnv.

Чтобы использовать venv для автоматического создания и активирования виртуального окружения, необходимо добавить в файл ~/.config/direnv/direnvrc следующий код (см. документацию).

Создание виртуального окружения

Если в файл .envrc добавить строчку

layout python-venv

то при переходе в папку будет direnv создаст виртуальное окружение в папке direnv, например .direnv/python-venv-3.7.3.
Чтобы создать виртуальное окружение с другим путем, например в более привычной папке venv, надо задать переменную VIRTUAL_ENV:

export VIRTUAL_ENV=.venv

Таким же способом можно подключать уже созданное виртуальное окружение.

Работа с разными версиями Python

Для установки отличной от системной версии python, нужно использовать команду:

layout python-venv python3.6

Создаем строку приглашения bash (PS1)

В отличие от ручной активации виртуального окружения, в нашем случае строка приглашения bash (PS1) не будет изменена (обычно она выглядит как (venv) user@comp:~$ ). Чтобы вернуть показ активации виртуального окружения в консоли нужно в файл ~/.bashrc добавить следующий код:

show_virtual_env() {
  if [[ -n "$VIRTUAL_ENV" && -n "$DIRENV_DIR" ]]; then
    echo "($(basename $VIRTUAL_ENV))"
  fi
}
export -f show_virtual_env
PS1='$(show_virtual_env)'$PS1

Пример файла настройки файла .envrc

Вот так может выглядеть файл .envrc настроенный для разработки flask-приложения:

export VIRTUAL_ENV=venv
layout python-venv
export FLASK_APP=app.py
export FLASK_DEBUG=1

Это позволяет автоматически активировать виртуальное окружение и загрузить переменные окружения при входе в папку с проектом.

terminal_direnv

Автор: Андрей

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js