Flask 配置管理
任何应用都需要配置——数据库地址、密钥、调试模式开关等。
Flask 提供了灵活的配置系统,支持从多种来源加载配置,满足开发和生产的不同需求。
Config 对象基础
Flask 应用的配置存储在 app.config 中,它像一个字典,可以用键名读写任何配置值:
实例
from flask import Flask
app = Flask(__name__)
# 直接设置配置项
app.config["SECRET_KEY"] = "your-secret-key"
app.config["DEBUG"] = True
app.config["DATABASE"] = "runoob.db"
# 读取配置
print(app.config["SECRET_KEY"]) # 输出: your-secret-key
print(app.debug) # 输出: True(DEBUG 可通过 app.debug 属性访问)
app = Flask(__name__)
# 直接设置配置项
app.config["SECRET_KEY"] = "your-secret-key"
app.config["DEBUG"] = True
app.config["DATABASE"] = "runoob.db"
# 读取配置
print(app.config["SECRET_KEY"]) # 输出: your-secret-key
print(app.debug) # 输出: True(DEBUG 可通过 app.debug 属性访问)
配置键名 必须全部大写,这是 Flask 的约定,配合配置加载方法使用。
内置配置项
Flask 内置了大量配置项来控制框架行为,以下是开发中最常用的:
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| DEBUG | bool | None | 是否开启调试模式(生产环境必须为 False) |
| TESTING | bool | False | 是否开启测试模式 |
| SECRET_KEY | str | None | 用于签名 Session 的密钥(必设) |
| SERVER_NAME | str | None | 服务器域名+端口,如 "example.com:5000" |
| MAX_CONTENT_LENGTH | int | None | 请求体最大大小(字节),用于限制上传 |
| SESSION_COOKIE_NAME | str | "session" | Session Cookie 的名称 |
| PERMANENT_SESSION_LIFETIME | timedelta | 31 天 | 永久 Session 的有效期 |
从 Python 文件加载——from_pyfile
最常见的做法是将配置写入单独的 Python 文件,然后加载:
# 文件路径:config.py(与 app.py 同级目录) # 注意:所有键名必须大写 SECRET_KEY = "your-production-secret-key" DATABASE_URL = "postgresql://user:pass@localhost/db" MAX_CONTENT_LENGTH = 16 * 1024 * 1024 # 限制上传文件大小 16MB # 开发配置 DEBUG = True
app.py 代码:
# 文件路径:app.py
from flask import Flask
app = Flask(__name__)
# 加载 config.py 中所有大写的变量到 app.config
app.config.from_pyfile("config.py")
print(app.config["DATABASE_URL"]) # 输出: postgresql://user:pass@localhost/db
从环境变量加载——from_prefixed_env
从环境变量加载是 12-Factor App 推荐的做法,最适合生产环境部署。
Flask 默认读取 FLASK_ 前缀的环境变量,值会被尝试解析为 JSON 类型:
# 在终端设置环境变量(或写入 .flaskenv 文件) export FLASK_SECRET_KEY="prod-secret" export FLASK_MAX_CONTENT_LENGTH=16777216
app.py 代码:
from flask import Flask
from datetime import timedelta
app = Flask(__name__)
# 加载默认配置
app.config["PERMANENT_SESSION_LIFETIME"] = timedelta(days=7)
# 自动加载所有以 FLASK_ 开头的环境变量
# 例如 FLASK_SECRET_KEY 会成为 config["SECRET_KEY"]
app.config.from_prefixed_env()
# 也可以自定义前缀
# app.config.from_prefixed_env("RUNOOB") # 加载 RUNOOB_ 前缀的变量
嵌套配置
使用双下划线 __ 可以设置嵌套配置:
$ export FLASK_DATABASE__HOST="localhost" $ export FLASK_DATABASE__PORT="5432"
加载后的结果:
实例
app.config.from_prefixed_env()
# config["DATABASE"] 的值为 {"host": "localhost", "port": 5432}
print(app.config["DATABASE"]) # 输出: {'host': 'localhost', 'port': 5432}
# config["DATABASE"] 的值为 {"host": "localhost", "port": 5432}
print(app.config["DATABASE"]) # 输出: {'host': 'localhost', 'port': 5432}
从 JSON/TOML 加载——from_file
除了 Python 文件和环境变量,Flask 还支持从 JSON、TOML 等格式加载配置:
实例
// 文件路径:config.json
{
"SECRET_KEY": "runoob-secret",
"DATABASE_URL": "sqlite:///runoob.db",
"ITEMS_PER_PAGE": 20
}
{
"SECRET_KEY": "runoob-secret",
"DATABASE_URL": "sqlite:///runoob.db",
"ITEMS_PER_PAGE": 20
}
实例
import json
app = Flask(__name__)
# 从 JSON 文件加载(text=True 表示文本模式,默认即为 True)
app.config.from_file("config.json", load=json.load)
# 从 TOML 文件加载(需要 tomllib 或 tomli)
# import tomllib
# app.config.from_file("config.toml", load=tomllib.load, text=False)
app = Flask(__name__)
# 从 JSON 文件加载(text=True 表示文本模式,默认即为 True)
app.config.from_file("config.json", load=json.load)
# 从 TOML 文件加载(需要 tomllib 或 tomli)
# import tomllib
# app.config.from_file("config.toml", load=tomllib.load, text=False)
从对象加载——from_object
直接从一个 Python 对象(模块或类)中加载所有大写属性:
实例
# 推荐做法:定义配置类,区分环境
class Config:
SECRET_KEY = "dev-key"
DATABASE = "dev.db"
class ProductionConfig(Config):
DEBUG = False
DATABASE = "prod.db"
class DevelopmentConfig(Config):
DEBUG = True
# 根据环境变量选择配置
import os
config_mode = os.environ.get("FLASK_CONFIG", "development")
if config_mode == "production":
app.config.from_object(ProductionConfig)
else:
app.config.from_object(DevelopmentConfig)
class Config:
SECRET_KEY = "dev-key"
DATABASE = "dev.db"
class ProductionConfig(Config):
DEBUG = False
DATABASE = "prod.db"
class DevelopmentConfig(Config):
DEBUG = True
# 根据环境变量选择配置
import os
config_mode = os.environ.get("FLASK_CONFIG", "development")
if config_mode == "production":
app.config.from_object(ProductionConfig)
else:
app.config.from_object(DevelopmentConfig)
instance 文件夹——私密配置
有些配置不适宜提交到代码仓库(如生产环境的密钥),可以放在 instance 文件夹中:
实例
app = Flask(__name__, instance_relative_config=True)
# 加载 instance/config.py(这个文件不提交到 Git)
app.config.from_pyfile("config.py", silent=True)
# instance 文件夹通常在项目目录外的独立位置
# 加载 instance/config.py(这个文件不提交到 Git)
app.config.from_pyfile("config.py", silent=True)
# instance 文件夹通常在项目目录外的独立位置
myflaskapp/
├── app.py
├── config.py # 公共配置(可提交到 Git)
└── instance/ # 不提交到 Git(.gitignore)
└── config.py # 私密配置(密钥等)
配置加载优先级
一个实践中最常见的配置加载顺序:
实例
app = Flask(__name__)
# 1. 加载默认配置(代码中的硬编码默认值)
app.config.update({
"ITEMS_PER_PAGE": 20,
"MAX_CONTENT_LENGTH": 16 * 1024 * 1024,
})
# 2. 加载实例配置(instance/config.py,优先级高于默认值)
app.config.from_pyfile("config.py", silent=True)
# 3. 加载环境变量(优先级最高,覆盖前面所有设置)
app.config.from_prefixed_env()
# 1. 加载默认配置(代码中的硬编码默认值)
app.config.update({
"ITEMS_PER_PAGE": 20,
"MAX_CONTENT_LENGTH": 16 * 1024 * 1024,
})
# 2. 加载实例配置(instance/config.py,优先级高于默认值)
app.config.from_pyfile("config.py", silent=True)
# 3. 加载环境变量(优先级最高,覆盖前面所有设置)
app.config.from_prefixed_env()
这样的优先级确保:默认值最弱,文件配置中等,环境变量最强——符合 12-Factor App 最佳实践。
