Обработка конфигурации
Приложениям необходима некая конфигурация. Существуют различные настройки, которые вы можете изменить в зависимости от среды приложения, например, включение режима отладки, установка секретного ключа и другие специфичные для среды параметры.
При разработке 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='192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'
)
Среда и функции отладки
Значения конфигурации 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
$ set -x 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 secrets; print(secrets.token_hex())' '192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'
Не раскрывайте секретный ключ при публикации вопросов или коммитах кода.
По умолчанию:
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 получить доступ к cookies, помеченным как «только HTTP», для обеспечения безопасности.
По умолчанию:
True
-
SESSION_COOKIE_SECURE -
Браузеры будут отправлять cookies только с запросами по HTTPS, если cookie помечен как «безопасный». Приложение должно быть доступно по HTTPS для того, чтобы это имело смысл.
По умолчанию:
False
-
SESSION_COOKIE_SAMESITE -
Ограничить способ отправки cookies с запросами с внешних сайтов. Может быть установлено в
'Lax'(рекомендуется) или'Strict'. См. Параметры Set-Cookie.По умолчанию:
NoneЖурнал изменений
Новое в версии 1.0.
-
PERMANENT_SESSION_LIFETIME -
Если
session.permanentистинно, срок действия cookie будет установлен на это количество секунд в будущем. Может бытьdatetime.timedeltaилиint.Встроенная реализация cookie Flask проверяет, что криптографическая подпись не старше этого значения.
По умолчанию:
timedelta(days=31)(2678400секунд)
-
SESSION_REFRESH_EACH_REQUEST -
Управляет тем, отправляется ли cookie с каждым ответом, когда
session.permanentистинно. Отправка 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не установлен. Современные браузеры не позволят устанавливать cookies для доменов без точки. Чтобы использовать домен локально, добавьте все имена, которые должны быть перенаправлены на приложение, в свой файл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. Если это отключено, возвращаемый из
jsonifyJSON будет содержать символы 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чтобы отключить предупреждение.
Журнал изменений
Изменено в версии 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 -x 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 = '192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'
Убедитесь, что конфигурация загружается очень рано, чтобы расширения могли получить доступ к конфигурации при запуске. В объекте 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)
Настройка из переменных окружения
Помимо указания на файлы конфигурации с помощью переменных окружения, вам может быть полезно (или необходимо) управлять значениями конфигурации непосредственно из окружения. Flask можно настроить на загрузку всех переменных окружения, начинающихся со специфического префикса, в config с помощью from_prefixed_env().
Переменные окружения могут быть установлены в оболочке перед запуском сервера:
$ export FLASK_SECRET_KEY="5f352379324c22463451387a0aec5d2f" $ export FLASK_MAIL_ENABLED=false $ flask run * Running on http://127.0.0.1:5000/
$ set -x FLASK_SECRET_KEY "5f352379324c22463451387a0aec5d2f" $ set -x FLASK_MAIL_ENABLED false $ flask run * Running on http://127.0.0.1:5000/
> set FLASK_SECRET_KEY="5f352379324c22463451387a0aec5d2f" > set FLASK_MAIL_ENABLED=false > flask run * Running on http://127.0.0.1:5000/
> $env:FLASK_SECRET_KEY = "5f352379324c22463451387a0aec5d2f" > $env:FLASK_MAIL_ENABLED = "false" > flask run * Running on http://127.0.0.1:5000/
Переменные затем можно загрузить и получить доступ к ним в config с ключом, равным имени переменной окружения без префикса, т.е.
app.config.from_prefixed_env() app.config["SECRET_KEY"] # Is "5f352379324c22463451387a0aec5d2f"
Префикс по умолчанию FLASK_. Это настраивается с помощью аргумента prefix from_prefixed_env().
Значения будут распарсены для попытки преобразования в тип, более специфичный, чем строки. По умолчанию используется json.loads(), поэтому возможны любые допустимые JSON-значения, включая списки и словари. Это настраивается с помощью аргумента loads from_prefixed_env().
При добавлении булевого значения с помощью стандартного парсинга JSON, только “true” и “false”, строчные, являются допустимыми значениями. Имейте в виду, что любая непустая строка рассматривается как True в Python.
Можно задавать ключи во вложенных словарях, разделяя ключи двойным подчёркиванием (__). Любые промежуточные ключи, которые не существуют в родительском словаре, будут инициализированы пустым словарем.
$ export FLASK_MYAPI__credentials__username=user123
app.config["MYAPI"]["credentials"]["username"] # Is "user123"
В Windows ключи переменных окружения всегда заглавные, поэтому вышеприведённый пример превратится в MYAPI__CREDENTIALS__USERNAME.
Для ещё более продвинутых функций загрузки конфигурации, включая слияние и регистронезависимую поддержку Windows, попробуйте специализированную библиотеку, такую как Dynaconf, которая включает интеграцию с Flask.
Рекомендации по конфигурированию
Недостатком подхода, упомянутого ранее, является то, что он усложняет тестирование. В общем случае нет единственного решения на 100%, но есть несколько моментов, которые можно учитывать для улучшения этого опыта:
- Создайте свое приложение в функции и зарегистрируйте схемы на нем. Таким образом, вы можете создавать несколько экземпляров приложения с различными прикрепленными конфигурациями, что значительно упрощает тестирование отдельных модулей. Вы можете использовать это для передачи конфигурации по мере необходимости.
- Не пишите код, которому требуется конфигурация во время импорта. Если вы ограничитесь доступом к конфигурации только по запросу, вы сможете переконфигурировать объект позже по мере необходимости.
- Убедитесь, что конфигурация загружается очень рано, чтобы расширения могли получить доступ к конфигурации при вызове
init_app.
Разработка/Производство
Большинству приложений требуется более одной конфигурации. Должны быть отдельные конфигурации для сервера производства и конфигурации, используемой во время разработки. Самый простой способ справиться с этим — использовать стандартную конфигурацию, которая всегда загружается и является частью контроля версий, и отдельную конфигурацию, которая переопределяет значения по мере необходимости, как показано в примере выше:
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 и значительно упрощает разработку и развертывание, так как позволяет быстро и легко переключаться между различными конфигурациями, не изменяя код. Если вы часто работаете над разными проектами, вы можете даже создать свою собственную скрипт для задания, которая активирует 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/pythonX.Y/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–2022 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/2.1.x/config/