Сообщить об ошибке.

Способы хранения, загрузки и переключения конфигураций Flask

Содержание:


Хранение и загрузка конфигурации Flask из файлов Python.

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

Общий шаблон таков:

app = Flask(__name__)
app.config.from_object('yourapplication.default_settings')
app.config.from_envvar('YOURAPPLICATION_SETTINGS')

Сначала шаблон загружает конфигурацию из модуля yourapplication.default_settings, а затем заменяет значения содержимым файла, на который указывает переменная среды YOURAPPLICATION_SETTINGS. Эту переменную среды можно установить в терминале перед запуском сервера:

# bash Linux
$ export YOURAPPLICATION_SETTINGS=/path/to/settings.cfg
$ flask run
 * Running on http://127.0.0.1:5000/

# CMD Windows
> set YOURAPPLICATION_SETTINGS=\path\to\settings.cfg
> flask run
 * Running on http://127.0.0.1:5000/

# Powershell Windows
> $env:YOURAPPLICATION_SETTINGS = "\path\to\settings.cfg"
> flask run
 * Running on http://127.0.0.1:5000/

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

Вот пример файла конфигурации:

# Пример конфигурации
SECRET_KEY = b'_5#y2L"F4Q8z\n\xec]/'

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

Хранение и загрузка конфигурации Flask из .json, .toml и т. д.

Также можно загрузить конфигурацию из файла в любом формате по вашему выбору с помощью метода объекта конфигурации app.config.from_file(). Например, чтобы загрузить из файла в формате TOML:

import toml
app.config.from_file("config.toml", load=toml.load)

Или из файла JSON:

import json
app.config.from_file("config.json", load=json.load)

Загрузка конфигурации Flask из переменных среды окружения.

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

Переменные среды можно установить в оболочке терминала перед запуском сервера:

# bash Linux
$ export SECRET_KEY="5f352379324c22463451387a0aec5d2f"
$ export MAIL_ENABLED=false
$ flask run
 * Running on http://127.0.0.1:5000/

# CMD Windows
> set SECRET_KEY="5f352379324c22463451387a0aec5d2f"
> set MAIL_ENABLED=false
> flask run
 * Running on http://127.0.0.1:5000/

Важно помнить, что переменные среды являются строками - они не десериализуются автоматически в типы Python. Смотрите пример файла конфигурации, в котором используются переменные среды:

import os

_mail_enabled = os.environ.get("MAIL_ENABLED", default="true")
MAIL_ENABLED = _mail_enabled.lower() in {"1", "t", "true"}

SECRET_KEY = os.environ.get("SECRET_KEY")

if not SECRET_KEY:
    raise ValueError("No SECRET_KEY set for Flask application")

Обратите внимание, что любое значение, кроме пустой строки, будет интерпретироваться как логическое значение True в Python, что требует осторожности, если среда явно устанавливает значения, предназначенные для False.

Чтобы расширения имели возможность доступа к конфигурации при запуске, необходимо загружать конфигурацию как можно раньше.

Есть и другие методы для объекта конфигурации для загрузки из отдельных файлов. Для получения полной справки прочтите документацию по объекту flask.Config.

Некоторые рекомендации по настройке приложений на Flask.

Минусом подходов разобранных выше является то, что они усложняют тестирование. В целом не существует единого 100% решения этой проблемы, но есть несколько вещей, которые могут улучшить этот опыт:

  1. Создавайте экземпляр веб-приложения в функции и регистрируйте в нем схемы blueprint. Таким образом, можно создать несколько экземпляров приложения с разными подключенными конфигурациями, что значительно упростит модульное тестирование. Такой подход можно использовать для передачи конфигурации по мере необходимости.
  2. Не пишите код, который требует настройки во время импорта.

Переключение конфигураций.

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

app = Flask(__name__)
app.config.from_object('yourapplication.default_settings')
app.config.from_envvar('YOURAPPLICATION_SETTINGS')

Затем нужно добавить отдельный файл config.py и экспортировать YOURAPPLICATION_SETTINGS=/path/config.py, и все готово. Но есть и альтернативные способы. Например, можно использовать импорт или создание подклассов.

В мире Django, очень популярно в файле конфигурации делать явный импорт, добавив from yourapplication.default_settings import * в начало файла, а затем переопределять изменения вручную. Во Flask, например, можно проверять переменную среды окружения, такую ​​как YOURAPPLICATION_MODE, которой при запуске будет передаваться значение 'production', 'development' и т.д. и на основе этого значения импортировать различные, жестко закодированные файлы конфигурации.

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

Интересным шаблоном также является использование классов и наследования:

class Config(object):
    TESTING = False

class ProductionConfig(Config):
    DATABASE_URI = 'mysql://user@localhost/foo'

class DevelopmentConfig(Config):
    DATABASE_URI = "sqlite:////tmp/foo.db"

class TestingConfig(Config):
    DATABASE_URI = 'sqlite:///:memory:'
    TESTING = True

Чтобы включить такую ​​конфигурацию, нужно вызвать app.config.from_object():

app.config.from_object('configmodule.ProductionConfig')

Обратите внимание, что app.config.from_object() не создает экземпляр объекта класса. Если нужно создать экземпляр класса, например, для доступа к свойству, то необходимо сделать это перед вызовом app.config.from_object():

from configmodule import ProductionConfig
app.config.from_object(ProductionConfig())

# Alternatively, import via string:
from werkzeug.utils import import_string
cfg = import_string('configmodule.ProductionConfig')()
app.config.from_object(cfg)

Создание экземпляра объекта конфигурации позволяет использовать декоратор @property в классах конфигурации:

class Config(object):
    """Базовая конфигурация, использует 
    промежуточный сервер баз данных."""
    TESTING = False
    DB_SERVER = '192.168.1.56'

    @property
    def DATABASE_URI(self):  # Note: all caps
        return f"mysql://user@{self.DB_SERVER}/foo"

class ProductionConfig(Config):
    """Использует сервер базы данных для production."""
    DB_SERVER = '192.168.19.32'

class DevelopmentConfig(Config):
    DB_SERVER = 'localhost'

class TestingConfig(Config):
    DB_SERVER = 'localhost'
    DATABASE_URI = 'sqlite:///:memory:'

Есть много разных способов, и вам решать, как нужно управлять файлами конфигурации.

Дополнительно смотрите как можно загружать конфигурации из папки экземпляра приложения.

Переменные окружения из модуля dotenv.

Команда flask поддерживает установку любого параметра для любой команды с переменными среды. Переменные называются FLASK_OPTION или FLASK_COMMAND_OPTION, например, FLASK_APP или FLASK_RUN_PORT.

Можно использовать поддержку dotenv в Flask для автоматической установки переменных среды вместо передачи параметров при запуске команды.

Если установлен модуль python-dotenv, то запуск команды flask установит переменные среды, определенные в файлах .env и .flaskenv. Можно также указать дополнительный файл для загрузки с опцией --env-file. Файлы dotenv можно использовать, чтобы не задавать вручную параметр CLI --app или FLASK_APP, а также задавать конфигурацию с использованием переменных среды, подобно тому, как работают некоторые службы развертывания.

Переменные, установленные в командной строке, используются вместо тех, которые установлены в .env и .flaskenv. Переменные, определяемые в .flaskenv следует использовать для общедоступных переменных, таких как FLASK_APP, а переменные, определяемые в .env не следует фиксировать в репозитории, т.к. файл используется для частных переменных.

Каталоги сканируются вверх от каталога, из которого вызывается команда flask.

Файлы переменных среды загружаются только командой flask или вызовом flask.run(). Если необходимо загрузить эти файлы при работе в рабочей среде, то следует вручную вызвать flask.cli.load_dotenv().

Настройка параметров команды.

Модуль click настроен на загрузку значений по умолчанию для параметров команды из переменных среды. Переменные используют шаблон FLASK_COMMAND_OPTION. Например, чтобы установить порт для команды запуска приложение, вместо flask run --port 8000 :

# Linux
$ export FLASK_RUN_PORT=8000
$ flask run
 * Running on http://127.0.0.1:8000/

# Windows
> set FLASK_RUN_PORT=8000
> flask run
 * Running on http://127.0.0.1:8000/

Их можно добавить в файл .flaskenv так же, как FLASK_APP, для управления параметрами команд по умолчанию.

Отключение dotenv.

Команда flask покажет сообщение, если обнаружит файлы dotenv и при этом python-dotenv не был установлен.

$ flask run
 * Tip: There are .env files present. Do "pip install python-dotenv" to use them.

Можно указать Flask не загружать файлы dotenv, даже если установлен python-dotenv, установив переменную среды FLASK_SKIP_DOTENV. Такое поведение может быть полезно, если необходимо загрузить их вручную или если используется средство запуска проекта, которое загружает их. Имейте в виду, что переменные среды должны быть установлены до загрузки приложения, иначе оно не будет настроено должным образом.

$ export FLASK_SKIP_DOTENV=1
$ flask run

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

Если нет необходимости устанавливать поддержку dotenv, то все равно можно установить переменные среды, добавив их в конец скрипта активации virtualenv. Активация virtualenv установит переменные.

# Linux
$ source .venv/bin/activate
$ export FLASK_APP=yourapplication
$ flask run --debug

# Windows
> source venv\Scripts\activate.bat
> set FLASK_APP=yourapplication
> flask run --debug

Вместо такого запуска предпочтительнее использовать поддержку модуля dotenv, так как файл .flaskenv можно зафиксировать в репозитории, чтобы он работал автоматически при извлечении проекта.