项目配置
使用类组织配置文件
在实际需求中,往往需要不同的配置组合。
例如,开发用的配置,测试用的配置,生产环境用的配置。为了能方便地在这些配置中切换,可以把配置文件升级为包,然后为这些使用场景分别创建不同的配置文件,但是最方便的做法是在单个配置文件中使用 Python 类来组织多个不同类别的配置。
现在它包含一个基本配置类(BaseConfig),还有其他特定的配置类,即测试配置类(TestingConfig)、开发配置类(DevelopmentConfig)和生产配置类(ProductionConfig),这些特定配置类都继承自基本配置类。
configs.py:使用 Python 类组织配置
# filename:configs.py
import logging
import os
class BaseConfig:
SECRET_KEY = os.getenv("SECRET_KEY", "dev key")
# mysql 数据库的配置信息
SQLALCHEMY_DATABASE_URI = ""
# redis配置
REDIS_HOST = "127.0.0.1"
REDIS_PORT = 6379
LOG_LEVEL = logging.DEBUG
class DevelopmentConfig(BaseConfig):
"""开发配置"""
SQLALCHEMY_DATABASE_URI = (
"mysql+pymysql://root:mysql@127.0.0.1:3306/zhengxin_flask_forum"
)
SQLALCHEMY_TRACK_MODIFICATIONS = False
class TestingConfig(BaseConfig):
"""测试配置"""
SQLALCHEMY_DATABASE_URI = "sqlite:///:memory:" # 内存数据库
class ProductionConfig(BaseConfig):
"""生成环境配置"""
SQLALCHEMY_DATABASE_URI = (
"mysql+pymysql://root:mysql@127.0.0.1:3306/zhengxin_flask_forum"
)
SQLALCHEMY_TRACK_MODIFICATIONS = False
config = {
"development": DevelopmentConfig,
"testing": TestingConfig,
"production": ProductionConfig,
}
在环境的配置中,为不同的使用场景设置了不同的数据库 URL,避免互相干扰。
在配置文件的底部,创建了一个存储配置名称和对应配置类的字典,用于在创建程序实例时通过配置名称来获取对应的配置类。 现在在创建程序实例后使用 app.config.from_object()
方法加载配置
# filename: app.py
import os
from flask import Flask
from configs import config
app = Flask(__name__)
# 尝试从本地环境中读取
config_name = os.getenv('FLASK_CONFIG', 'development')
app.config.from_object(config[config_name])
@app.route('/')
def hello_world():
return 'Hello World!'
我们首先从配置文件中导入匹配配置名到配置类的 config
字典。为了方便修改配置类型,配置名称会先从环境变量 FLASK_CONFIG
中导入,从环境变量加载配置可以方便地在不改动代码的情况下切换配置。
然后再环境变量中,添加内容
FLASK_DEBUG=True
FLASK_RUN_HOST='127.0.0.1'
FLASK_RUN_PORT=5000
FLASK_APP=app.py
FLASK_CONFIG=development
初始化扩展
在后面我们会用到数据库之类的第三方拓展,为了方便管理这些拓展,可以将所有的第三方库放在一个文件里面进行导入创建。
为了方便管理所有的第三方库,我们可以所有的库放在 extensions.py
文件中实例化一个数据库对象 db 。
使用数据库的时候,需要安装 flask-sqlalchemy
拓展数据库的安装,
poetry add flask-sqlalchemy
poetry add pymysql
# filename:extensions.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
然后再在工厂函数中将数据库对象绑定到 app
对象。
大部分扩展都提供了一个 init_app() 方法来⽀持分离扩展的实例化和初始化操作。
现在我们仍然像往常一样初始化扩展类,但是并不传入程序实例。这时扩展类实例化的工作可以集中放到 extensions.py 脚本中
# filename:app.py
from extensions import db
app = Flask(__name__)
...
# 注册插件
db.init_app(app)
由于后面我们还会绑定更多的拓展库,到时候可以使用同样的方法进行注册
@集成日志
在 config.py
文件中在不同的环境的配置下添加日志级别
class Config(object):
...
# 默认日志等级
LOG_LEVEL = logging.DEBUG
class ProductionConfig(Config):
"""生产模式下的配置"""
LOG_LEVEL = logging.ERROR
在项目录下的 utils.py
文件中添加日志配置的相关方法。
在整个项目中后面还会有大量工具函数或者工具类,可以专门用一个文件放在一起管理。
import logging
from logging.handlers import RotatingFileHandler
from configs import config
def setup_log(config_name):
"""配置日志"""
# 设置日志的记录等级
logging.basicConfig(level=config[config_name].LOG_LEVEL) # 调试debug级
# 创建日志记录器,指明日志保存的路径、每个日志文件的最大大小、保存的日志文件个数上限
file_log_handler = RotatingFileHandler("logs/log", maxBytes=1024 * 1024 * 100, backupCount=10)
# 创建日志记录的格式 日志等级 输入日志信息的文件名 行数 日志信息
formatter = logging.Formatter('%(levelname)s %(filename)s:%(lineno)d %(message)s')
# 为刚创建的日志记录器设置日志记录格式
file_log_handler.setFormatter(formatter)
# 为全局的日志工具对象(flask app使用的)添加日志记录器
logging.getLogger().addHandler(file_log_handler)
在 create_app
方法中调用上一步创建的方法,并传入 config_name
# filename: app.py
from utils import setup_log
...
app = Flask(__name__)
# 尝试从本地环境中读取
config_name = os.getenv('FLASK_CONFIG', 'development')
setup_log(config_name)
app.config.from_object(config[config_name])
...
在项目根目录下创建日志目录文件夹 logs
,如下:
- 创建的
logs
文件中 - 在
logs
文件夹下创建.gitkeep
文件,以便能将logs
文件夹添加到远程仓库 - 并在
.gitignore
文件中添加忽略提交生成的日志文件
logs/log*
在 Flask 框架中,其自己对 Python 的 logging 进行了封装,在 Flask 应用程序中,可以以如下方式进行输出 log:
current_app.logger.debug('debug')
current_app.logger.error('error')
当前应用程序的 logger 会根据应用程序的调试状态去调整日志级别
然后新建 logs 目录,在其中新建 .gitkeep
.gitkeep
这个文件可以让 logs 目录被 git 追踪。