Spec-Zone.ru › Flask 1.1

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

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

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_ENV для управления средой отдельно от режима отладки. Среда разработки включает режим отладки.

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

$ export FLASK_ENV=development
$ flask run

(В Windows используйте set вместо export.)

Рекомендуется использовать переменные среды, как описано выше. Хотя можно установить 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

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

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

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

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

SESSION_COOKIE_NAME

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

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

SESSION_COOKIE_DOMAIN

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

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

SESSION_COOKIE_PATH

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

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

SESSION_COOKIE_HTTPONLY

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

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

SESSION_COOKIE_SECURE

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

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

SESSION_COOKIE_SAMESITE

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

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

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

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

PERMANENT_SESSION_LIFETIME

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

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

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

SESSION_REFRESH_EACH_REQUEST

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

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

USE_X_SENDFILE

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

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

SEND_FILE_MAX_AGE_DEFAULT

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

По умолчанию: timedelta(hours=12) (43200 секунд)

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

Сериализуйте объекты в ASCII-кодированном JSON. Если это отключено, JSON будет возвращен как строка Юникод или закодирован как UTF-8 с помощью jsonify. Это имеет последствия для безопасности при отображении 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

Настройка из файлов

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

Поэтому распространенный подход такой:

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

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

$ export YOURAPPLICATION_SETTINGS=/path/to/settings.cfg
$ python run-app.py
 * Running on http://127.0.0.1:5000/
 * Restarting with reloader...

В системах Windows используйте встроенную функцию set вместо неё:

> set YOURAPPLICATION_SETTINGS=\path\to\settings.cfg

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

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

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

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

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

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

Переменные среды можно установить в Linux или OS X с помощью команды export в командной оболочке перед запуском сервера:

$ export SECRET_KEY='5f352379324c22463451387a0aec5d2f'
$ export MAIL_ENABLED=false
$ python run-app.py
 * Running on http://127.0.0.1:5000/

В системах Windows используйте встроенную функцию set вместо неё:

> set SECRET_KEY='5f352379324c22463451387a0aec5d2f'

Хотя этот подход прост в использовании, важно помнить, что переменные среды являются строками — они не десериализуются автоматически в типы 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):
    DEBUG = False
    TESTING = False
    DATABASE_URI = 'sqlite:///:memory:'

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

class DevelopmentConfig(Config):
    DEBUG = True

class TestingConfig(Config):
    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."""
    DEBUG = False
    TESTING = False
    DB_SERVER = '192.168.1.56'

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

class ProductionConfig(Config):
    """Uses production database server."""
    DB_SERVER = '192.168.19.32'

class DevelopmentConfig(Config):
    DB_SERVER = 'localhost'
    DEBUG = True

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

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

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

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

Изменения

Введено в версии 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/python2.X/site-packages/myapp
    $PREFIX/var/myapp-instance
    

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

Поскольку объект конфигурации обеспечивал загрузку файлов конфигурации из относительных имён файлов, мы позволили изменить загрузку по именам файлов на относительные к пути экземпляра при необходимости. Поведение относительных путей в файлах конфигурации можно переключить между «относительно корня приложения» (по умолчанию) и «относительно папки экземпляра» с помощью переключателя 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–2020 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/1.1.x/config/

Spec-Zone.ru

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