1. 將配置寫在Python文件中
- 配置文件(config.py 或 settings.py) 通常放置在程序源代碼的目錄,方便引用
配置文件
# settings.py class Config(object): DEBUG = False TESTING = False DATABASE_URI = 'sqlite://:memory:' class ProductionConfig(Config): DATABASE_URI = 'mysql://user@localhost/foo' class DevelopmentConfig(Config): DEBUG = True class TestingConfig(Config): TESTING = True
讀取
import importlib
path = 'settings.Foo'
p,c = path.rsplit('.',maxsplit=1)
m = importlib.import_module(p)
# m = __import__(p)
cls = getattr(m,c)
for key in dir(cls):
if key.isupper():
print(key,getattr(cls,key))
這種方法非常簡單,直接把配置的內容寫到了代碼中,在應用中直接進行引用。另外也可以把這個py配置文件放到其他python應用中,修改具體的配置內容即可。但是,它存在嚴重的安全問題,我們都知道不應該把配置寫到代碼中,如果有人把我們的源代碼上傳到了github中,那么數據庫的配置就相當於向全世界公開了。當然,當配置文件不包含敏感信息時,也可以采用這種簡單的方法。
2. 利用外部配置文件
更常見的配置管理方法就是利用外部的配置文件,讓配置文件僅僅包含配置信息,和代碼獨立開來,不直接引用也就不需要寫成python代碼。通常使用json、yaml或者ini的文件格式來存儲配置。
利用configparse
寫入文件
import configparser
config = configparser.ConfigParser()
config["DEFAULT"] = {'ServerAliveInterval': '45',
'Compression': 'yes',
'CompressionLevel': '9',
'ForwardX11':'yes'
}
config['bitbucket.org'] = {'User':'hg'}
config['topsecret.server.com'] = {'Host Port':'50022','ForwardX11':'no'}
with open('example.ini', 'w') as file:
config.write(file)
配置文件
# example.ini [DEFAULT] serveraliveinterval = 45 compression = yes compressionlevel = 9 forwardx11 = yes [bitbucket.org] user = hg [topsecret.server.com] host port = 50022 forwardx11 = no
除此之外,我們還可以用json文件來存儲
# config.json
{
"DATABASE": {
"host": "localhost",
"dbname": "test",
"user": "user",
"password": "password",
"port": 3306
}
}
結合環境變量和python庫configparser讀取外部文件,首先在開發通常不會接觸到生產環境,因此生產環境的配置文件由運維來寫,運維將應用所需要的配置寫好后,放到生產服務器的指定位置,代碼從指定位置讀取配置。為了方便程序的統一調試,可以提前約定好一個系統環境變量(CONFIG_PATH)來指定配置文件的存放路徑。
export CONFIG_PATH = /home/test/configs/config.ini
讀取的代碼如下:
import os
import configparser
try:
CONFIG_PATH = os.environ['CONFIG_PATH']
except Exception:
raise ValueError
config = configparser.ConfigParser()
config.read(CONFIG_PATH)
host = config["DATABASE"]["HOST"]
3. 直接使用系統環境變量讀取配置
此方法不使用文件來存儲配置信息,將所有的配置信息存儲到環境變量中,在實踐中也比較常見,運維通過ansible部署腳本,在程序運行前將需要配置信息導入到環境變量中。
import os
secret_key = os.environ.get('SECRET_KEY', None)
if not secret_key:
raise ValueError('You must have "SECRET_KEY" variable')
app.config['SECRET_KEY'] = secert_key
不利用文件存儲,在一定程度上加強了對密碼等配置信息的保護,但也增加了運維的工作量,尤其當需要修改配置的時候。
4. Dynaconf:Pyhton項目的動態配置
上面介紹了三種常見的項目配置方法,最有介紹一個好用的python動態項目配置庫:Dynaconf。dyanconf是OSM(Object Settings Mapper), 能夠從不同的配置數據存儲方式中讀取配置,例如python配置文件、系統環境變量、redis、ini文件、json文件等等。
安裝:pip install dynaconf
使用方式:
from dynaconf import settings
print(settings.SOME_VARIABLE)
or
print(settings.get('SOME_VARIABLE'))
如果不希望配置跟隨項目,可以通過系統環境變量來指定配置文件的位置
# using module name export DYNACONF_SETTINGS=myproject.production_settings # or using location path export DYNACONF_SETTINGS=/etc/myprogram/settings.py
4.1 dyanconf讀取系統環境變量中的配置
當我們部署的程序需要讀取一個MYSQL_HOST的配置用於測試,不需要去重寫配置文件,僅需要再系統環境變量中加入:
export DYNACONF_MYSQL_HOST=myserver.com
然后,程序便可以獲取到該配置:
>>> from dynaconf import settings >>> print(settings.MYSQL_HOST) myserver.com
如果需要指定配置值的數值類型,則通過以下方式增加對應的系統環境變量:
export DYNACONF_NUMBER='@int 123'
export DYNACONF_FLOAT='@float 12.2'
export DYNACONF_FLAG='@bool yes'
export DYNACONF_FLAG2='@bool disabled'
export DYNACONF_LIST='@json [1, 2, 3, 4]'
export DYNACONF_DICT='@json {"name": "Bruno"}'
讀取到的配置如下所示:
from dynaconf import settings type(settings.NUMBER) int type(settings.FLOAT) float type(settings.FLAG) bool print(settings.FLAG2 == False) True print(settings.LIST[1]) 2 print(settings.DICT['name']) Bruno
4.2 通過redis存儲配置
我們也可以講配置文件存儲到redis中,達到在對不同的機器共享環境變量的效果,僅需要在settings.py文件中增加一下代碼:
# connection
REDIS_FOR_DYNACONF = {
'host': 'localhost',
'port': 6379,
'db': 0
}
# and loader
LOADERS_FOR_DYNACONF = [
'dynaconf.loaders.env_loader',
'dynaconf.loaders.redis_loader' # 增加了redis的加載
]
現在可以講配置存儲到redis中,hash默認為DYNACONF_DYNACONF。dyanconf還提供了方法去將配置寫入到redis:
from dynaconf.utils import redis_writer from dynaconf import settings redis_writer.write(settings,name='test',mysql_host='localhost', MYSQL_PORT=3306)
查看Redis,存儲的結果如下:
DYNACONF_DYNACONF:
NAME='test'
MYSQL_HOST='localhost'
PORT='@int 3306'
至此,python項目常見的配置方法總結完畢,不過在一些微服務架構中,會專門開發配置中心,程序直接從線上讀取配置,配置的管理也會開發一套GUI,方便開發和運維。
