Spec-Zone.ru › Flask 2.0

Обработка конфигурации

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

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

Независимо от того, как вы загружаете свою конфигурацию, доступен объект конфигурации, который хранит загруженные значения конфигурации: атрибут config объекта Flask. Именно сюда Flask помещает определенные значения конфигурации, а также расширения могут помещать свои значения конфигурации. Но здесь вы также можете хранить свою собственную конфигурацию.

Основные принципы конфигурации

Атрибут config фактически является подклассом словаря и может быть изменён так же, как и любой словарь:

app = Flask(__name__)
app.config['TESTING'] = True

Определённые значения конфигурации также передаются объекту Flask, так что вы можете читать и записывать их оттуда:

app.testing = True

Для обновления нескольких ключей одновременно можно использовать метод dict.update():

app.config.update(
    TESTING=True,
    SECRET_KEY=b'_5#y2L"F4Q8z\n\xec]/'
)

Среда и функции отладки

Значения конфигурации ENV и DEBUG являются особыми, потому что их изменение после начала настройки приложения может привести к непредсказуемым результатам. Для надёжной установки режима среды и отладки Flask использует переменные окружения.

Среда используется для указания Flask, расширениям и другим программам, таким как Sentry, в какой среде работает Flask. Она контролируется переменной окружения FLASK_ENV и по умолчанию установлена в production.

Установка FLASK_ENV в development включит режим отладки. flask run будет по умолчанию использовать интерактивный отладчик и перезагрузчик в режиме отладки. Чтобы управлять этим отдельно от среды, используйте флаг FLASK_DEBUG.

Журнал изменений

Изменено в версии 1.0: Добавлена возможность управления средой отдельно от режима отладки. Среда разработки включает режим отладки.

Для переключения Flask на среду разработки и включения режима отладки установите FLASK_ENV:

$ export FLASK_ENV=development
$ flask run
> set FLASK_ENV=development
> flask run
> $env:FLASK_ENV = "development"
> flask run

Рекомендуется использование переменных среды, как описано выше. Хотя можно установить ENV и DEBUG в вашей конфигурации или коде, это настоятельно не рекомендуется. Они не могут быть прочитаны командой flask на ранней стадии, и некоторые системы или расширения могут быть уже настроены на основе предыдущего значения.

Встроенные значения конфигурации

Следующие значения конфигурации используются внутри Flask:

ENV

В какой среде запущено приложение. Flask и расширения могут включать поведение, основанное на среде, например, включение режима отладки. Атрибут env соответствует этому ключу конфигурации. Он устанавливается переменной окружения FLASK_ENV и может вести себя непредсказуемо, если установлен в коде.

Не включайте режим разработки при развертывании в производстве.

По умолчанию: 'production'

Журнал изменений

Новое в версии 1.0.

DEBUG

Включен ли режим отладки. При использовании flask run для запуска сервера разработки будет показан интерактивный отладчик для необработанных исключений, и сервер будет перезагружен при изменениях кода. Атрибут debug соответствует этому ключу конфигурации. Он включен, когда ENV равен 'development', и переопределяется переменной окружения FLASK_DEBUG. Он может вести себя непредсказуемо, если установлен в коде.

Не включайте режим отладки при развертывании в производстве.

По умолчанию: True если ENV равно 'development', или False в противном случае.

TESTING

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

По умолчанию: False

PROPAGATE_EXCEPTIONS

Исключения повторно поднимаются, а не обрабатываются обработчиками ошибок приложения. Если не установлено, это подразумевается, если TESTING или DEBUG включены.

По умолчанию: None

PRESERVE_CONTEXT_ON_EXCEPTION

Не удалять контекст запроса при возникновении исключения. Если не установлено, это верно, если DEBUG истинно. Это позволяет отладчикам инспектировать данные запроса при ошибках, и обычно не нужно устанавливать это напрямую.

По умолчанию: None

TRAP_HTTP_EXCEPTIONS

Если нет обработчика для исключения типа HTTPException, повторно поднять его для обработки интерактивным отладчиком вместо возврата его как простого ответа об ошибке.

По умолчанию: False

TRAP_BAD_REQUEST_ERRORS

Попытка получить доступ к ключу, который не существует, из словарей запроса, таких как args и form, вернёт страницу ошибки 400 Bad Request. Включите это, чтобы обработать ошибку как необработанное исключение, чтобы вы получили интерактивный отладчик. Это более конкретная версия TRAP_HTTP_EXCEPTIONS. Если не установлено, оно включено в режиме отладки.

По умолчанию: None

SECRET_KEY

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

$ python -c 'import os; print(os.urandom(16))'
b'_5#y2L"F4Q8z\n\xec]/'

Не раскрывайте секретный ключ при публикации вопросов или коммитах кода.

По умолчанию: None

SESSION_COOKIE_NAME

Название cookie сессии. Может быть изменено, если у вас уже есть cookie с таким же именем.

По умолчанию: 'session'

SESSION_COOKIE_DOMAIN

Правило соответствия домена, для которого cookie сессии будет действительным. Если не указано, cookie будет действительным для всех поддоменов SERVER_NAME. Если False, домен cookie не будет установлен.

По умолчанию: None

SESSION_COOKIE_PATH

Путь, для которого cookie сессии будет действительным. Если не указано, cookie будет действительным под APPLICATION_ROOT или / если это не установлено.

По умолчанию: None

SESSION_COOKIE_HTTPONLY

Браузеры не позволят JavaScript получить доступ к cookie, помеченным как «только HTTP», для обеспечения безопасности.

По умолчанию: True

SESSION_COOKIE_SECURE

Браузеры будут отправлять cookie только с запросами по HTTPS, если cookie помечен как «защищенный». Приложение должно быть доступно по HTTPS, чтобы это имело смысл.

По умолчанию: False

SESSION_COOKIE_SAMESITE

Ограничить отправку cookie с запросов с внешних сайтов. Может быть установлено в 'Lax' (рекомендуется) или 'Strict'. См. Параметры Set-Cookie.

По умолчанию: None

Журнал изменений

Новое в версии 1.0.

END_OF_DOCUMENT_MARKER
PERMANENT_SESSION_LIFETIME

Если session.permanent равно true, срок действия cookie будет установлен через это количество секунд в будущем. Может быть либо datetime.timedelta, либо int.

Реализация cookie Flask проверяет, что криптографическая подпись не старше этого значения.

По умолчанию: timedelta(days=31) (2678400 секунд)

SESSION_REFRESH_EACH_REQUEST

Управляет отправкой cookie с каждым ответом, когда session.permanent равно true. Отправка cookie каждый раз (по умолчанию) более надёжно предотвращает истечение срока действия сессии, но потребляет больше пропускной способности. На временные сессии это не влияет.

По умолчанию: True

USE_X_SENDFILE

При подаче файлов задаёт заголовок X-Sendfile вместо подачи данных с Flask. Некоторые веб-серверы, такие как Apache, распознают это и подают данные более эффективно. Это имеет смысл только при использовании такого сервера.

По умолчанию: False

SEND_FILE_MAX_AGE_DEFAULT

При подаче файлов устанавливает максимальное время кеширования в секундах. Может быть либо datetime.timedelta, либо int. Переопределите это значение на основе файла, используя get_send_file_max_age() в приложении или модуле.

Если None, send_file сообщает браузеру использовать условные запросы вместо кэширования по времени, что обычно предпочтительнее.

По умолчанию: None

SERVER_NAME

Информирует приложение о том, к какому хосту и порту оно привязано. Требуется для поддержки сопоставления маршрутов для поддоменов.

Если установлено, будет использоваться для домена cookie сессии, если SESSION_COOKIE_DOMAIN не установлено. Современные веб-браузеры не позволят устанавливать cookie для доменов без точки. Чтобы использовать домен локально, добавьте все имена, которые должны маршрутизироваться к приложению, в свой файл hosts.

127.0.0.1 localhost.dev

Если установлено, url_for может генерировать внешние URL-адреса только с контекстом приложения, а не с контекстом запроса.

По умолчанию: None

APPLICATION_ROOT

Информирует приложение о том, под каким путём оно смонтировано приложением/веб-сервером. Используется для генерации URL-адресов за пределами контекста запроса (внутри запроса, диспетчер отвечает за установку SCRIPT_NAME вместо; см. Обработка приложений для примеров конфигурации диспетчера).

Будет использоваться для пути cookie сессии, если SESSION_COOKIE_PATH не установлено.

По умолчанию: '/'

PREFERRED_URL_SCHEME

Использовать этот протокол для генерации внешних URL-адресов при отсутствии контекста запроса.

По умолчанию: 'http'

MAX_CONTENT_LENGTH

Не читать более этого количества байтов из входящих данных запроса. Если не установлено и запрос не указывает CONTENT_LENGTH, данные не будут считываться для обеспечения безопасности.

По умолчанию: None

JSON_AS_ASCII

Сериализовать объекты в JSON с кодировкой ASCII. Если отключено, возвращаемый JSON из jsonify будет содержать символы Unicode. Это имеет последствия для безопасности при рендеринге JSON в JavaScript в шаблонах и, как правило, должно оставаться включённым.

По умолчанию: True

JSON_SORT_KEYS

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

По умолчанию: True

JSONIFY_PRETTYPRINT_REGULAR

Ответы jsonify будут выводиться с новой строкой, пробелами и отступами для лучшей читаемости человеком. Всегда включено в режиме отладки.

По умолчанию: False

JSONIFY_MIMETYPE

MIME-тип ответов jsonify.

По умолчанию: 'application/json'

TEMPLATES_AUTO_RELOAD

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

По умолчанию: None

EXPLAIN_TEMPLATE_LOADING

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

По умолчанию: False

MAX_COOKIE_SIZE

Выводить предупреждение, если заголовки cookie превышают это количество байтов. По умолчанию 4093. Более крупные cookie могут быть проигнорированы браузерами. Установите значение 0 для отключения предупреждения.

Changelog

Изменено в версии 1.0: LOGGER_NAME и LOGGER_HANDLER_POLICY были удалены. См. Ведение журнала для информации о конфигурации.

Добавлен ENV для отражения переменной среды FLASK_ENV.

Добавлен SESSION_COOKIE_SAMESITE для управления параметром SameSite cookie сессии.

Добавлен MAX_COOKIE_SIZE для управления предупреждением Werkzeug.

Новое в версии 0.11: SESSION_REFRESH_EACH_REQUEST, TEMPLATES_AUTO_RELOAD, LOGGER_HANDLER_POLICY, EXPLAIN_TEMPLATE_LOADING

Новое в версии 0.10: JSON_AS_ASCII, JSON_SORT_KEYS, JSONIFY_PRETTYPRINT_REGULAR

Новое в версии 0.9: PREFERRED_URL_SCHEME

Новое в версии 0.8: TRAP_BAD_REQUEST_ERRORS, TRAP_HTTP_EXCEPTIONS, APPLICATION_ROOT, SESSION_COOKIE_DOMAIN, SESSION_COOKIE_PATH, SESSION_COOKIE_HTTPONLY, SESSION_COOKIE_SECURE

Новое в версии 0.7: PROPAGATE_EXCEPTIONS, PRESERVE_CONTEXT_ON_EXCEPTION

Новое в версии 0.6: MAX_CONTENT_LENGTH

Новое в версии 0.5: SERVER_NAME

Новое в версии 0.4: LOGGER_NAME

Конфигурация из файлов Python

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

Поэтому распространённым шаблоном является следующий:

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

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

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

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

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

# Example configuration
SECRET_KEY = b'_5#y2L"F4Q8z\n\xec]/'

Убедитесь, что конфигурация загружается очень рано, чтобы расширения могли получить к ней доступ при запуске. В объекте config также есть другие методы для загрузки из отдельных файлов. Для полного справочника прочитайте документацию по объекту 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)

Настройка из переменных окружения

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

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

$ export SECRET_KEY="5f352379324c22463451387a0aec5d2f"
$ export MAIL_ENABLED=false
$ flask run
 * Running on http://127.0.0.1:5000/
> set SECRET_KEY="5f352379324c22463451387a0aec5d2f"
> set MAIL_ENABLED=false
> flask run
 * Running on http://127.0.0.1:5000/
> $env:SECRET_KEY = "5f352379324c22463451387a0aec5d2f"
> $env: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.

Убедитесь, что конфигурация загружается очень рано, чтобы расширения могли получить доступ к конфигурации при запуске. Также есть другие методы объекта config для загрузки из отдельных файлов. Для полной справки, прочитайте документацию класса Config.

Рекомендации по настройке

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

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

Разработка / Производство

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

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

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

В мире Django очень популярен подход явного импорта в файле конфигурации, добавив from yourapplication.default_settings import * в начало файла, а затем переопределяя изменения вручную. Вы также можете просмотреть переменную окружения, например, 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

Для активации такой конфигурации просто обратитесь к from_object():

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

Обратите внимание, что from_object() не создаёт объект класса. Если вам нужно создать экземпляр класса, например, для доступа к свойству, то это необходимо сделать до вызова 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):
    """Base config, uses staging database server."""
    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):
    """Uses production database server."""
    DB_SERVER = '192.168.19.32'

class DevelopmentConfig(Config):
    DB_SERVER = 'localhost'

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

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

  • Сохраняйте стандартную конфигурацию в системе управления версиями. Либо заполните конфигурацию этой стандартной конфигурацией, либо импортируйте её в собственные файлы конфигурации перед переопределением значений.
  • Используйте переменную окружения для переключения между конфигурациями. Это можно сделать вне интерпретатора Python и значительно упрощает разработку и развертывание, поскольку вы можете быстро и легко переключаться между различными конфигурациями, не изменяя код. Если вы часто работаете над разными проектами, вы можете даже создать собственную программу для активации виртуальной среды и экспорта конфигурации разработки для вас.
  • Используйте инструмент, подобный fabric, в производственной среде, чтобы отдельно распространять код и конфигурации на серверы производства. Для некоторых подробностей о том, как это сделать, перейдите к паттерну Развёртывание с Fabric.

Папки экземпляров

Changelog

В версии 0.8.

Flask 0.8 представляет папки экземпляров. Flask долгое время позволял ссылаться на пути, относительные к папке приложения напрямую (через Flask.root_path). Именно так многие разработчики загружали конфигурации, хранимые рядом с приложением. К сожалению, однако, это работает хорошо только если приложения не являются пакетами, в этом случае корневой путь относится к содержимому пакета.

В Flask 0.8 был добавлен новый атрибут: Flask.instance_path. Он относится к новому понятию — «папке экземпляра». Папка экземпляра предназначена для того, чтобы не попадать под контроль версий и быть специфичной для развертывания. Это идеальное место для размещения данных, которые либо изменяются во время выполнения, либо конфигурационные файлы.

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

app = Flask(__name__, instance_path='/path/to/instance/folder')

Пожалуйста, помните, что этот путь должен быть абсолютным, если он указан.

Если параметр instance_path не указан, используются следующие значения по умолчанию:

  • Модуль без установки:

    /myapp.py
    /instance
    
  • Пакет без установки:

    /myapp
        /__init__.py
    /instance
    
  • Установленный модуль или пакет:

    $PREFIX/lib/pythonX.Y/site-packages/myapp
    $PREFIX/var/myapp-instance
    

    $PREFIX — это префикс вашей установки Python. Это может быть /usr или путь к вашей виртуальной среде. Вы можете напечатать значение sys.prefix , чтобы увидеть, чему установлено значение префикса.

Поскольку объект config обеспечивал загрузку файлов конфигурации из относительных имён файлов, мы сделали возможным изменение загрузки через имена файлов, чтобы они были относительными к пути экземпляра, если это необходимо. Поведение относительных путей в файлах конфигурации может быть изменено с «относительно корня приложения» (значение по умолчанию) на «относительно папки экземпляра» с помощью переключателя instance_relative_config в конструктор приложения:

app = Flask(__name__, instance_relative_config=True)

Вот полный пример того, как настроить Flask для предварительной загрузки конфигурации из модуля и затем переопределения конфигурации из файла в папке экземпляра, если он существует:

app = Flask(__name__, instance_relative_config=True)
app.config.from_object('yourapplication.default_settings')
app.config.from_pyfile('application.cfg', silent=True)

Путь к папке экземпляра можно найти в Flask.instance_path. Flask также предоставляет сокращение для открытия файла из папки экземпляра с помощью Flask.open_instance_resource().

Пример использования обоих:

filename = os.path.join(app.instance_path, 'application.cfg')
with open(filename) as f:
    config = f.read()

# or via open_instance_resource:
with app.open_instance_resource('application.cfg') as f:
    config = f.read()

© 2007–2021 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/2.0.x/config/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API