網上搜刮到的一個config策略

ps:最近比較愁一些開發初始的設計問題,比較菜鳥經驗不足,吸收一些前輩的經驗之sql

-----------------------------------------------shell

Flask很讚的特色之一就是可擴展性強,很是靈活,對於config來講也是如此。Flask官方文檔中已經說起了很是多的方法,以及一些有用的建議。我在Flask項目開發中的config實踐,則是基於文檔中提到的類繼承方案,並經過環境變量來切換不一樣的config配置。數據庫

需求

比較好的config方案是怎樣的呢?我以爲有以下幾點:flask

  • 針對不一樣的環境分離配置(Development、Production等)
  • 可以方便地在不一樣配置之間切換
  • 適用於多人協做
  • 易於維護

從這些需求點出發,下面分享一下我在Flask項目中的實踐經驗。api

項目結構

/project_root
    /config
        __init__.py
        default.py
        development.py
        development_sample.py
        production.py
        production_sample.py
        testing.py
    /project
        __init__.py
        ...

全部的配置文件都存放在config包中,而Flask app則位於project包。對config包中不一樣文件的作簡單的說明:服務器

  • __init__.py:在這裏定義加載配置的函數
  • default.py:默認配置
  • development.py(不簽入Git):用於開發的config,每一個開發人員的development config能夠自定義
  • development_sample.pydevelopment.py的模板,每當有新成員加入dev團隊時,只需將其另存爲development.py,而後根據本身的狀況填充對應項便可
  • production.py(不簽入Git):用於生產服務器的config,最好是由專人來管理production.py,其餘dev須要在服務器增長config項,一概向此人申請
  • production_sample.pyproduction.py的模板,填好後能夠scp到服務器端
  • testing.py:用於測試的配置,測試的config應該是環境無關的(好比通常會使用sqlite數據庫進行測試,這樣就無需配置帳號密碼了),因此須要簽入Git中

config類繼承結構

採用了基於類繼承的config結構,保存默認配置的Config類做爲基類,其餘類繼承之,以下:app

# default.py
class Config(object):
    ...

# development.py
class DevelopmentConfig(Config)
    ...

# production.py
class ProductionConfig(Config)
    ...

# testing.py
class TestingConfig(Config)
    ...

這樣作的好處首先在於,經過繼承達到了config複用的目的。第二個好處來自IDE,好比PyCharm能夠對類中屬性是否爲override進行提示,以下圖:ide

Image Title

有圈圈+向上箭頭標誌的行就是override自父類,沒有的就是本身定義的啦,一目瞭然。函數

加載策略

以前提到過,在config/__init__.py中會定義用於加載config的函數,加載策略以下:測試

  • 讀取環境變量MODE,根據MODE的取值加載不一樣的config
  • MODE環境變量不存在(或不合法),則默認加載development config
  • 若development config沒法導入,則使用default config

用代碼表達就是:

# coding: UTF-8
import os

def load_config():
    """加載配置類"""
    mode = os.environ.get('MODE')
    try:
        if mode == 'PRODUCTION':
            from .production import ProductionConfig
            return ProductionConfig
        elif mode == 'TESTING':
            from .testing import TestingConfig
            return TestingConfig
        else:
            from .development import DevelopmentConfig
            return DevelopmentConfig
    except ImportError, e:
        from .default import Config
        return Config

加載config

在定義好config結構以後,就能夠加載了。須要儘早加載config,以便flask的一些第三方插件可以讀取配置,好比Flask-SQLAlchemy:

from flask import Flask
from config import load_config  # 絕對導入
from .models import db

def create_app():
    """建立Flask app"""
    app = Flask(__name__)

    # Load config
    config = load_config()
    app.config.from_object(config)

    db.init_app(app)
    ...

使用config

from flask import current_app

config = current_app.config
SITE_DOMAIN = config.get('SITE_DOMAIN')

切換config

經過改變環境變量MODE來切換config,在不一樣應用場景下有不一樣的方法:

能夠在代碼中直接改變環境變量:

import os

os.environ['MODE'] = 'TESTING'

在使用Fabric部署時,能夠經過shell_env設置環境變量

from fabric.api import shell_env

with shell_env(MODE='PRODUCTION'):
    # do something

在使用Supervisor管理Gunicorn進程時,能夠經過environment配置項來設置環境變量:

[program:project_name]
command = /var/www/project/venv/bin/gunicorn -c deploy/gunicorn.conf wsgi:app
directory = /var/www/project
user = deploy
autostart = true
autorestart = true
environment = MODE="PRODUCTION"

我的建議在生產服務器上默認啓用PRODUCTION模式,能夠在/etc/profile末尾添加一行:

export MODE=PRODUCTION
相關文章
相關標籤/搜索