Обработка конфигурации
Приложениям необходима какая-то конфигурация. Есть разные настройки, которые вы можете изменить в зависимости от среды приложения, например, включение режима отладки, установка секретного ключа и другие специфичные для среды вещи.
Дизайн Flask обычно требует, чтобы конфигурация была доступна при запуске приложения. Вы можете закодировать конфигурацию в код, что для многих небольших приложений не так уж и плохо, но есть лучшие способы.
Независимо от того, как вы загружаете свою конфигурацию, доступен объект config, который содержит загруженные значения конфигурации: атрибут 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 -
Секретный ключ, который будет использоваться для безопасного шифрования куки сессии и может использоваться для любых других задач безопасности расширениями или вашим приложением. Он должен быть длинной случайной строкой байтов, хотя принимается и юникод. Например, скопируйте вывод этого в свою конфигурацию:
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 -
Укажите приложению путь, под которым оно смонтировано приложением/веб-сервером.
Будет использоваться для пути cookie сессии, если
SESSION_COOKIE_PATHне задан.По умолчанию:
'/'
-
PREFERRED_URL_SCHEME -
Используйте эту схему для генерации внешних URL-адресов, когда вы не находитесь в контексте запроса.
По умолчанию:
'http'
-
MAX_CONTENT_LENGTH -
Не читайте более этого количества байтов из данных входящего запроса. Если не задано и запрос не указывает
CONTENT_LENGTH, никакие данные не будут считаны для обеспечения безопасности.По умолчанию:
None
-
JSON_AS_ASCII -
Сериализуйте объекты в JSON с кодировкой ASCII. Если это отключено, JSON будет возвращён как строка Unicode или закодирован как
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для отключения предупреждения.
Изменено в версии 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, что значительно упрощает разработку и развертывание, так как вы можете быстро и легко переключаться между различными конфигурациями, не изменяя код. Если вы часто работаете над различными проектами, вы можете даже создать собственный скрипт для импорта, который активирует virtualenv и экспортирует для вас конфигурацию разработки.
- Используйте инструмент, такой как 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или путь к вашему virtualenv. Вы можете распечатать значение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.0.x/config/