Python配置文件實現


實現目標:

  • 支持配置文件繼承
  • 支持本地配置文件
  • 支持配置文件別名
  • 簡單的配置文件操作

最新的代碼可以參考 https://github.com/blackmatrix7/matrix-toolkit/blob/master/toolkit/config.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2017/8/18 上午9:31
# @Author : Matrix
# @Github : https://github.com/blackmatrix7/
# @Blog : http://www.cnblogs.com/blackmatrix/
# @File : config.py
# @Software: PyCharm
import os

__author__ = 'blackmatrix'


class ConfigMixin:

    """
    Config混合類,支持部分dict協議,實現以類似操作dict的方式操作配置文件。
    """

    def __setattr__(self, key, value):
        raise AttributeError

    def __setitem__(self, key, value):
        raise AttributeError

    def __delitem__(self, key):
        raise AttributeError

    def __getitem__(self, item):
        try:
            return getattr(self, item)
        except AttributeError as ex:
            raise KeyError('{0} object has no key {1}'.format(self.__class__.__name__, item)) from ex

    def __iter__(self):
        return (k for k in dir(self) if k.upper() == k)

    def __contains__(self, key):
        return hasattr(self, key)

    def items(self):
        return {k: getattr(self, k, None) for k in dir(self) if k.upper() == k}.items()

    def get(self, item, value=None):
        return getattr(self, item, value)


class BaseConfig(ConfigMixin):
    """
    配置文件基類
    """
    # 項目路徑
    PROJ_PATH = os.path.abspath('')


def get_current_config(config_name='default'):
    """
    對本地配置文件的支持,當項目根目錄存在localconfig.py文件時
    優先從localconfig.py中讀取配置,如果不存在讀取config.py的配置。
    localconfig.py 應該加入git的忽略文件
    :return:
    """
    try:
        from localconfig import configs
        current_config = configs[config_name]
    except ImportError:
        from config import configs
        current_config = configs[config_name]
    return current_config

使用示例:

在項目根目錄創建 config.py 和 localconfig.py。

localconfig.py可以不創建(如果不需要本地配置文件的話),如果創建localconfig.py,需要在.gitignore中,將localconfig.py排除掉。

當項目根目錄同時存在config.py 和 localconfig.py時,優先讀取localconfig.py的配置項。

config.py 完整代碼:

from toolkit.config import BaseConfig, get_current_config

__author__ = 'blackmatrix'


class DefaultConfig(BaseConfig):

    """
    配置文件的具體實現,所有的配置項都必須是全部大寫
    """

    # DEBUG
    DEBUG = False

    # Cache
    CACHE_MEMCACHED_SERVERS = ['127.0.0.1:11211']
    CACHE_KEY_PREFIX = ''

    # RabbitMQ
    RABBITMQ_HOST = '127.0.0.1'
    RABBITMQ_PORT = 5672
    RABBITMQ_USER = 'user'
    RABBITMQ_PASS = 'password'


"""
以下為測試用數據
"""


class BaseDemoConfig(BaseConfig):

    # HOST
    HOST = '127.0.0.1'

    """
    對於需要通過其他屬性運算獲得的屬性參數,需要定義在特性中
    """
    LOGIN_URL = property(lambda self: 'http://{host}/login'.format(host=self.HOST))


class DemoConfig01(BaseDemoConfig):
    # HOST
    HOST = '192.168.1.10'


class DemoConfig02(BaseDemoConfig):
    # HOST
    HOST = '10.10.10.10'


default = DefaultConfig()
demo01 = DemoConfig01()
demo02 = DemoConfig02()


configs = {'default': default,
           'demo01': demo01,
           'demo02': demo02}

# 讀取配置文件的名稱,在具體的應用中,可以從環境變量、命令行參數等位置獲取配置文件名稱
config_name = 'default'

current_config = get_current_config(config_name)

在config.py模塊中:

每套配置都為獨立的類,繼承自BaseConfig,並將其實例化。

如有必要,在多套配置文件類中,可以互相繼承。比如DemoConfig01繼承自BaseDemoConfig。

在配置文件類的繼承中,比較特別的是需要通過其他屬性參與運算獲取的配置項,需要使用property定義。

例如下面示例代碼的LOGIN_URL,需要通過HOST計算得來。

那么就必須寫成 LOGIN_URL = property(lambda self: 'http://{host}/login'.format(host=self.HOST))

而不能寫成 LOGIN_URL = 'http://{host}/login'.format(host=self.HOST) ,否則在配置文件類的繼承時,會出現和預想不一致的情況。

因為在父類(BaseDemoConfig)創建的時候,LOGIN_URL已經通過計算生成。

子類(DemoConfig01)繼承自BaseDemoConfig,即使對HOST進行修改,也不會影響到LOGIN_URL的值。那么子類的LOGIN_URL一直是父類創建時的狀態。

class BaseDemoConfig(BaseConfig):

    # HOST
    HOST = '127.0.0.1'

    """
    對於需要通過其他屬性運算獲得的屬性參數,需要定義在特性中
    """
    LOGIN_URL = property(lambda self: 'http://{host}/login'.format(host=self.HOST))


class DemoConfig01(BaseDemoConfig):
    # HOST
    HOST = '192.168.1.10'


class DemoConfig02(BaseDemoConfig):
    # HOST
    HOST = '10.10.10.10'


default = DefaultConfig()
demo01 = DemoConfig01()
demo02 = DemoConfig02()

configs變量為dict,存儲配置文件別名和對應的配置文件對象。

configs = {'default': default,
           'demo01': demo01,
           'demo02': demo02}

模塊存儲名為config_name的變量,為配置文件別名。

# 讀取配置文件的名稱,在具體的應用中,可以從環境變量、命令行參數等位置獲取配置文件名稱
config_name = 'default'

再聲明變量current_config,由get_current_config(config_name)取值,表示當前的配置文件。

get_current_config會根據配置文件別名,加載不同的配置項。

current_config = get_current_config(config_name)

localconfig.py也進行如此配置,甚至可以從config.py中繼承。

唯一不同的是,localconfig.py中,不需要聲明config_name和current_config變量。

配置文件的使用:

在需要使用配置項的代碼中,使用如下代碼導入當前的配置文件

# 讀取當前配置項
# current_config會根據當前的config_name獲取到匹配的配置文件對象
# 如果項目根目錄存在localconfig.py,則優先從localconfig.py中讀取
from config import current_config

獲取配置文件中的屬性

# 獲取配置文件中的屬性
# 配置文件對象,支持以.(點號)運算符獲取對象的屬性,也支持以key的形式獲取對象的屬性
# 以下兩種方式都能獲取的配置項
RABBITMQ_HOST = current_config.RABBIT_HOST
RABBITMQ_PORT = current_config['RABBITMQ_PORT']

配置文件支持遍歷

keys = [key for key in current_config]
assert isinstance(keys, list)
values = {k: v for k, v in current_config.items()}
assert isinstance(values, dict)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM