Обработка конфигурации
Приложениям нужна какая-то конфигурация. Есть разные настройки, которые вы можете изменить в зависимости от среды приложения, например, включение режима отладки, установка секретного ключа и другие специфичные для среды вещи.
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%-го решения для этой проблемы в общем случае, но есть несколько моментов, которые вы можете учитывать, чтобы улучшить этот опыт:
- Создавайте приложение в функции и регистрируйте шаблоны в ней. Таким образом, вы можете создавать несколько экземпляров приложения с разными прикрепленными конфигурациями, что упрощает тестирование. Вы можете использовать это для передачи необходимой конфигурации.
- Не пишите код, которому нужна конфигурация во время импорта. Если ограничиться доступом к конфигурации только во время запросов, вы можете переконфигурировать объект по мере необходимости.
Разработка/Производство
Большинству приложений требуется не одна, а несколько конфигураций. Должны быть отдельные конфигурации для сервера производства и для использования во время разработки. Самый простой способ сделать это — использовать стандартную конфигурацию, которая всегда загружается и является частью контроля версий, и отдельную конфигурацию, которая перезаписывает значения по мере необходимости, как показано в примере выше:
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/