如何写 python 项目 config 配置

理想情况下,只需要一个config文件

在简单的项目里,往往只需要一个配置文件就可以了。

配置文件写成yaml格式,然后使用yaml.load()就可以简单的使用

common.yaml文件

authorize:
  { token: justtoken,
    expire_time: 1200,
    reset_password_expire_time: 2400
  }

date_format: '%Y-%m-%d %H:%M:%S'

使用 python 读取

import yaml

config_file = open('common.yml')
CONF = yaml.safe_load(config_file)

print(CONF)

执行结果

{'authorize': {'token': 'justtoken', 'expire_time': 1200, 'reset_password_expire_time': 2400}, 'date_format': '%Y-%m-%d %H:%M:%S'}

生产环境的分离伴随着config的拆分

然而在实际的项目执行过程中,我们会把代码环境区分为正式环境和开发环境,与此同时就有

  • 正式环境数据库
  • 开发环境数据库

显然,一个config文件已经无法完成区分,所以需要两份config文件

dev.yml

db:
  { 
    SQLALCHEMY_DATABASE_URI: "mysql+pymysql://admin@localhost:3306/test?charset=utf8mb4"
  }

prod.yml

db:
  { 
    SQLALCHEMY_DATABASE_URI: "mysql+pymysql://admin@xxx:3306/prod?charset=utf8mb4"
  }

再使用一个环境变量来决定使用哪一个config文件

import os
import yaml

env = os.environ.get('env', 'dev')
if env == 'prod':
    config_file = open('prod.yml')
    CONF = yaml.safe_load(config_file)
elif env == 'dev':
    config_file = open('dev.yml')
    CONF = yaml.safe_load(config_file)
else:
    raise EnvironmentError('Environment error')

print(CONF)

注:

  • 使用 export 命令设置环境变量

    export env=“prod”

  • 如果没有设置环境变量,则默认为dev环境

    env = os.environ.get(‘env’, ‘dev’)

执行结果

当环境为dev时候

{'db': {'SQLALCHEMY_DATABASE_URI': 'mysql+pymysql://admin@localhost:3306/test?charset=utf8mb4'}}

当环境为prod时候

{'db': {'SQLALCHEMY_DATABASE_URI': 'mysql+pymysql://admin@xxx:3306/prod?charset=utf8mb4'}}

更进一步,敏感信息需要在config文件里面隐藏

像数据库密码,账号token之类的敏感信息是不应该写在代码里面的,别人一看得到了你的代码,就得到了你的账号和数据库的访问权。所以需要将敏感信息独立出来,不写在代码里面

  • 把敏感信息从config文件里面拿掉

  • 将敏感信息写在环境变量里面

  • 代码里面将敏感信息读取出来
    def load_env_outside():
    env_conf = dict()
    env_conf[‘database_password’] = os.environ.get(‘database_password’)
    return env_conf

  • 和现有的config做合并
    def merge_conf(base, to_be_merged):
    for i in to_be_merged.keys():
    base[i] = to_be_merged[i]
    return base

    if env == 'dev':
        dev_conf = load_env('dev.yml')
    elif env == 'prod':
        prod_conf = load_env('prod.yml')
        env_outside = load_env_outside()
        CONF = merge_conf(prod_conf, env_outside)
    else:
        raise EnvironmentError('Environment error')
    
    print(CONF)
    

执行结果为

{'db': {'SQLALCHEMY_DATABASE_URI': 'mysql+pymysql://admin@xxx:3306/prod?charset=utf8mb4'}, 'database_password': 'hello'}

注:

  • 执行环境为prod
  • 往往测试环境是可以直接写代码在config里面的,但是prod不行,所以测试环境没有做合并

(optional)减少出错的可能性,把公共部分的配置文件分离出来

程序在开发的时候,改了一个dev的config,但是没有改prod的config,最后上线的时候出了bug。这时候把公共的config单独提取出来,可以避免一部分这个问题

  • 提取共有config

举个例子 common.yml

authorize:
  { token: justtoken,
    expire_time: 1200,
    reset_password_expire_time: 2400
  }

date_format: '%Y-%m-%d %H:%M:%S'
  • 做合并

    import os
    import yaml
    env = os.environ.get('env', 'dev')
    
    
    def load_env(env_file_name):
        file = open(os.path.join(os.path.dirname(__file__), env_file_name), 'r', encoding='utf-8')
        cfg = yaml.safe_load(file)
        return cfg
    
    
    def merge_conf(base, to_be_merged):
        for i in to_be_merged.keys():
            base[i] = to_be_merged[i]
        return base
    
    
    def load_env_outside():
        env_conf = dict()
        env_conf['database_password'] = os.environ.get('database_password')
        return env_conf
    
    
    CONF = load_env('common.yml')
    
    if env == 'dev':
        dev_conf = load_env('dev.yml')
        CONF = merge_conf(CONF, dev_conf)
    elif env == 'prod':
        prod_conf = load_env('prod.yml')
        CONF = merge_conf(CONF, prod_conf)
        env_outside = load_env_outside()
        CONF = merge_conf(CONF, env_outside)
    else:
        raise EnvironmentError('Environment error')
    
    print(CONF)
    
    

执行结果

{'authorize': {'token': 'justtoken', 'expire_time': 1200, 'reset_password_expire_time': 2400}, 'date_format': '%Y-%m-%d %H:%M:%S', 'db': {'SQLALCHEMY_DATABASE_URI': 'mysql+pymysql://admin@xxx:3306/prod?charset=utf8mb4'}, 'database_password': 'hello'}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值