1. 程式人生 > >Python專案讀取配置的幾種方式

Python專案讀取配置的幾種方式

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://[email protected]/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,方便開發和運維。