Python配置文件实现

实现目标:python

  • 支持配置文件继承
  • 支持本地配置文件
  • 支持配置文件别名
  • 简单的配置文件操做

最新的代码能够参考 https://github.com/blackmatrix7/matrix-toolkit/blob/master/toolkit/config.pygit

#!/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

使用示例:github

在项目根目录建立 config.py 和 localconfig.py。测试

localconfig.py能够不建立(若是不须要本地配置文件的话),若是建立localconfig.py,须要在.gitignore中,将localconfig.py排除掉。spa

当项目根目录同时存在config.py 和 localconfig.py时,优先读取localconfig.py的配置项。命令行

config.py 完整代码:code

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模块中:orm

每套配置都为独立的类,继承自BaseConfig,并将其实例化。对象

若有必要,在多套配置文件类中,能够互相继承。好比DemoConfig01继承自BaseDemoConfig。blog

在配置文件类的继承中,比较特别的是须要经过其余属性参与运算获取的配置项,须要使用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)
相关文章
相关标签/搜索