实现目标:

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

最新的代码可以参考 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)

Python配置文件实现的更多相关文章

  1. python 配置文件__ConfigParser

    基础读取配置文件 -read(filename)               直接读取文件内容 -sections()                      得到所有的section,并以列表的形 ...

  2. python配置文件的加载

    背景: 微信机器人项目用到了mysql数据库配置,阿里云OSS上传文件配置:现在需要将这些配置参数统一写到一个配置文件中统一管理,而不是分散的写在代码中 1. 使用.ini文件作为配置文件 例如: s ...

  3. python配置文件转dict

    配置文件有很多种,如JSON,properties,conf,xml等. 除非需要跟别的语言进行交互,python本身是完全可以取代所有配置文件的.使用python进行配置可以使用非常灵活地执行一些逻 ...

  4. python配置文件读取

    在代码实现的过程中,我们经常选择将一些固定的参数值写入到一个单独的配置文件中.在python中读取配置文件官方提供了configParser方法. 主要有如下方法(找官文):   (这家伙很懒,直接复 ...

  5. python 配置文件 ConfigParser模块

    ConfigParser模块 用于生成和修改常见配置文档,当前模块的名称在 python 3.x 版本中变更为 configparser. 来看一个好多软件的常见文档格式如下 [DEFAULT] Se ...

  6. python配置文件

    python有两种配置文件,file.ini和file.json 一.ini文件如下: db_config.ini [baseconf] host=127.0.0.1 port=3306 user=r ...

  7. python配置文件configparser详解

    Python中一般需要配置文件,配置文件一般以.cfg, .conf, .ini结尾.配置文件可以将数据库抽离到以 .ini(Windows)结尾的文件中,这样做的优点在于可在配置文件中添加多个数据库 ...

  8. python:配置文件configparser

    #-*- coding:utf8 -*- # Auth:fulimei import configparser #第一个标签 conf=configparser.ConfigParser() conf ...

  9. python 配置文件返回的两种方式,写法不一样而已

    配置文件如下: [MODE]mode:{ "register":"all"} 或者 mode = {"register":"all ...

随机推荐

  1. MySQL安装出现的1045问题以及解决方法

    MySQL安装出现1045的问题解决办法: 1045.的原因是已经装过了MySQL再次装的时候报的错误,那么该怎么处理那??? 首先卸载程序,从windows里找到mysql右击卸载,然后就是在dos ...

  2. Android setContentView方法解析(一)

    在Activity的生命周期onCreate中.我们一般都习惯性的调用setContentView(int layoutResID)方法,把布局文件载入到页面上来.以下我们就来通过源代码一步步的分析怎 ...

  3. flask框架-decorator装饰器

    调用包: from functools import wraps 装饰器其实就是一个函数:参数是一个函数,返回值是一个函数 1.装饰器使用是通过@符号,在函数的上面 2.装饰器中定义的函数,要使用*a ...

  4. JAVA入门[3]—Spring依赖注入

    Spring支持属性注入和构造器注入,它支持XML和注解两种方式.本文介绍Spring控制反转容器加载包含beans的XML文件,实现依赖注入. 一.创建bean实例 暂且抛开对象依赖,我们先看下如何 ...

  5. lock锁速记

    1.Lock关键字主要实现锁互斥,确保一个线程A在请求此操作时不会被其线程B请求中断(假设A先请求并在没有未完成的操作情况下申请了此互斥锁).lock的参数必须是基于引用类型的对象,不要是基本类型像b ...

  6. springboot(十五):springboot+jpa+thymeleaf增删改查示例

    这篇文章介绍如何使用jpa和thymeleaf做一个增删改查的示例. 先和大家聊聊我为什么喜欢写这种脚手架的项目,在我学习一门新技术的时候,总是想快速的搭建起一个demo来试试它的效果,越简单越容易上 ...

  7. 体验mssql-cli

    1. 背景 安装SQL Server on Linux之后,在命令行下使用sqlcmd,你会发现代码提示,语法高亮,甚至连多行复制都不支持,相比之下,MySQL的命令行客户端还好用多了.只做简单的命令 ...

  8. SSH简单项目

    这是我学习SSH整合时的一个测试项目,代码比较简单 整个项目实现从数据库中取数据,在页面上显示.项目的结构如下: (1)数据库设计 数据库使用的是student数据库中的一个数据库表grade,表的内 ...

  9. [译文]React v16(新特性)

    [译文]React v16(新特性) 查看原文内容 我们很高兴的宣布React v16.0发布了! 这个版本有很多长期被使用者期待的功能,包括: fragments (返回片段类型) error bo ...

  10. JavaScript 中 this 的详解

    this 的指向 this 是 js 中定义的关键字,它自动定义于每一个函数域内,但是它的指向却让人很迷惑.在实际应用中,this 的指向大致可以分为以下四种情况. 原文作者:林鑫,作者博客:http ...