Skip to content

项目配置

使用类组织配置文件

在实际需求中,往往需要不同的配置组合。

例如,开发用的配置,测试用的配置,生产环境用的配置。为了能方便地在这些配置中切换,可以把配置文件升级为包,然后为这些使用场景分别创建不同的配置文件,但是最方便的做法是在单个配置文件中使用 Python 类来组织多个不同类别的配置。

现在它包含一个基本配置类(BaseConfig),还有其他特定的配置类,即测试配置类(TestingConfig)、开发配置类(DevelopmentConfig)和生产配置类(ProductionConfig),这些特定配置类都继承自基本配置类。

configs.py:使用 Python 类组织配置

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() 方法加载配置

python
# 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 中导入,从环境变量加载配置可以方便地在不改动代码的情况下切换配置。

然后再环境变量中,添加内容

txt
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 拓展数据库的安装,

shell
poetry add flask-sqlalchemy
poetry add pymysql
python
# filename:extensions.py 
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

然后再在工厂函数中将数据库对象绑定到 app 对象。

大部分扩展都提供了一个 init_app() 方法来⽀持分离扩展的实例化和初始化操作。

现在我们仍然像往常一样初始化扩展类,但是并不传入程序实例。这时扩展类实例化的工作可以集中放到 extensions.py 脚本中

python
# filename:app.py
from extensions import db  

app = Flask(__name__)

...

# 注册插件
db.init_app(app)  

由于后面我们还会绑定更多的拓展库,到时候可以使用同样的方法进行注册

@集成日志

config.py 文件中在不同的环境的配置下添加日志级别

python
class Config(object):
    ...

    # 默认日志等级
    LOG_LEVEL = logging.DEBUG


class ProductionConfig(Config):
    """生产模式下的配置"""
    LOG_LEVEL = logging.ERROR

在项目录下的 utils.py 文件中添加日志配置的相关方法。

在整个项目中后面还会有大量工具函数或者工具类,可以专门用一个文件放在一起管理。

python
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

python
# 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:

python
current_app.logger.debug('debug')
current_app.logger.error('error')

当前应用程序的 logger 会根据应用程序的调试状态去调整日志级别

然后新建 logs 目录,在其中新建 .gitkeep

.gitkeep 这个文件可以让 logs 目录被 git 追踪。