“
0x00 概要与阅读提示
笔者在做一些项目时,尝尝被管理配置文件所困,每次都在尝试使用不同的方法管理配置文件。有些项目适用一些前辈总结的方法,而有些项目不适用,本文正是笔者对于管理项目配置从不同角度进行的尝试,希望其中一种方法能够适用于读者的需求。
本文主要介绍如何实现代码在不同运行环境下,快速切换至适合当前环境的配置信息,避免碎片化的配置信息导致人工修改耗费本不必要的时间。如在测试环境和生产环境,显然我们在测试环境中的一些回显是不能够让在生产环境中的用户察觉的,但此时由于配置信息零散地分布在不同文件中,切换配置信息是极为不便的。
本文中的代码出现中文是为了更好的阅读,实际环境时尽可能地使用英文,避免不必要的异常。
”
0x01
—
磨刀不误砍柴工
我们知道在python3中的标准模块configparser,是可以对配置文件进行管理(增删改查)的,但这不能直接实现灵活地切换配置信息,它需要在每次读取配置时加入许多if判断环境,从而读取适合当前环境下的配置,这会导致大量冗余的代码,这不够pythonic。关于configparser的用法,已有很多文章介绍,不在此赘述。
既然不适合,那么我们就应该自己实现。
首先明确我们的需求:
1.区分环境(测试环境和生产环境):想一想在生产环境的时候开了debug模式;
2.通用配置:通用的配置能够减少我们修改配置文件的负担。
3.模块配置:若有同事在一块写项目时,我们无法保障对方有多少需要配置的信息,所以按模块划分配置文件是很有必要的。
4.集中地管理:各个模块通过一次性设置采用当前环境的配置。
其次选择实现方法,聪明的同学可能已经想到了:类。我们可以写一个配置类,用于【存储配置信息】,也就是我们的配置文件就是一个.py文件。
0x02
—
大浪淘沙-1
我们先实现简易地【区分环境】,【通用配置】的配置类。
显然,这能够在小型项目中运行得很好。但这将会导致一个问题,当每次使用配置时都将需要实例化该类。这不符合我们【集中地】管理配置文件的需求。当然也有一种妥协的解决方案,利用代码架构来解决(见0x03)。
0x03
—
大浪淘沙-2
对该目录树有一定了解后,先在文字叙述上理解如何在代码层面进行解决“每次配置时都需要实例化该类”的问题。
我们知道python中导入一个包时实际上就是导入了该包中的"__init__.py"文件,若"__init__.py"为空或无有效信息,那么"import App"这条语句只会导入"__init__.py"文件,并不导入".App/"目录下的模块。
由此,我们可以将"components"各个模块中需要获取配置的方法【注册】到".App/core.py"内核中,同时在内核中导入该配置类,仅需在内核中进行一次实例化,就可以被注册到内核中的各个方法使用。
我们来实现:(配置文件如0x02。若你对以下代码无法理解,建议手码一遍,或pip install itchat,参考itchat源码)
当然,这也导致了一个问题:“当有多个App应用时,无法【集中】地区分环境”。这是从代码架构层面妥协的一个方案,仅有少量App并打算不再添加App时可以尝试使用这种方案。
0x04
—
大浪淘沙-3
以上方案并不够通用且没有解决【模块配置】的需求,我们仍需改进。
为了将通用配置和模块配置区分开,这需要我们将所有可通用的配置分到【通用配置类】中,再将不同环境的配置信息分到其【环境配置类】中。
我们在区分环境这个条件下实现通用配置,配合使用supervisor设置环境变量(配置environment=env="TEST" ,不在此赘述)。当然也可以不使用supervisor,相信你能够自行实现以下提到的"conf/manager/__init__.py"文件中的env判断。
为了简便,不同环境的配置均在一个文件内实现,实际使用时按需求分文件。
先实现【区分环境】和【通用配置】:
为了能够区分环境,应在同目录下的"__init__.py"文件中加入if判断。
为了实现【模块配置】,又能够保障【集中地管理】。在上级目录下,创建不同模块的配置文件,如:
再在该目录下使其生效。
此时仅需在其他模块中导入conf即可。如:
或者相应模块导入配置时:
但这也带来了新的问题,当模块配置较多时,会导致调用者的困惑,因此写一个与同事交流的规范必不可少。
参考:
《如何优雅地管理项目配置》 陈鸣
《Python项目的配置管理》 keakon
十分感谢。往常写项目时就参考的这两位前辈的文章,同时基于这两篇文章,做此探索。
觉得不错,可以打赏哦~
领取专属 10元无门槛券
私享最新 技术干货