🍕 Easy Configuration(ezkfg)

GitHub: 🍕 Easy Configuration(ezkfg)

想说一下最近写的一个小项目,ezkfg。

为什么叫这个名呢?主要是因为(kfg,config,cfg,ezcfg,ezconfig)之类的名字都已经被占用了

其次就是,配置文件这个东西总是需求很多的,我在很多项目中都会用到,但是一直没找到一个自己喜欢的。与其不如自己造一个轮子,取其精华去其糟粕。

快来 pip install ezkfg !

几种配置方式

  • argparse:

    最常见的就是argparse的方式,支持很多数据类型,支持设置默认值,支持设置可选值,支持设置可选值的描述之类的。这个也是很多项目和我经常使用的方式,尤其是深度学习的项目,因为可以非常方便的指定实验参数。但是参数很难保留,要么就要手写文件读入,要么就在文件中传入 list 先进行参数解析。

  • config.py:

    这是除此上面的方式以外我最喜欢也是常用的形式了吧,因为毕竟是原生的 Python 内容,可以定义多个 config class,然后通过 from config import config_xxx as config 的方式导入,也挺方便配置,同时支持所有 Python 的数据类型。但是毕竟是要修改掉 import 包的信息,每次修改可能都要至少修改两个文件内的参数,容易让人困惑。

  • YAML:

    YAML 也算是非常灵活的配置文件类型,结构简单,而且可以通过文件读入,非常方便复现,支持列表之类的数据结构。是我很喜欢的配置文件类型。

  • json:

    同上,但是文件结构较为复杂,内容多了以后不太直观。

  • ini:

    方便选取多种配置,有内置的库支持,但是是没有数据类型的,读入全是字符串,需要手动进行数据转换,同时是 k-v 形式的,因此是没有层级的。

同时,我又看到了 addict 这个项目,嵌套的.进行属性调用真的还挺方便,但是没有文件的 IO。

明确需求

所以,还是要明确一下需求。

文件其实只是个载体,我个人认为文件格式的差异其实都是可以接受的,可能根据应用场景略有差别。比如我想要把我的实验内容发给其他人,或者在其他机器上快速复现,那么我用配置文件的方式显然要比其他方式优秀的多。

另外,在实验中调用的形式也是非常重要的,首先是参数的预加载。预加载时,有些参数我们是需要提供默认值的,而有些参数可能明显用不到,那么最好不要占用存储,简化配置文件的重量。

其次,数据类型是必要的,毕竟在实验中的参数可能是有多种形式的。

然后就是在 Code 中的参数引用,如果对于特定的参数,我希望能够利用嵌套的.实现层级的调用,而不是使用一长串的[]来调用。但是在另外一些场景,比如两种方法,但是两种方法有着相同的超参数,那么我用.来进行调用,很不利于代码的复用,更好的方式是config['method'].alpha的形式看起来会更加直观,这样我们就可以动态的修改method以使用对应的alpha值。因此,这两种形式都是必要的。

最后就是文件 IO 了,这个是必须支持的。如果你要在其他地方部署,显然直接用配置文件,不改动原项目任何代码的效果会好很多。

实现

首当其冲的就是属性调用和索引调用,这两个是必须实现的,而且都要支持嵌套。通过[]的索引调用其实没什么好说的,本来就是内置功能,因为在 Python 中每一个类其实都有一个__dict__变量,存储了类中的所有属性。所有的配置参数也是借用了这个字典来进行存储的。

首先是初始化,现在是支持几种初始化方式的,有字典,列表和Config类。dict就需要递归去解决,Config就用内置的update方法即可。

其中__getitem____setitem__方法就是用__getattr____setattr__调用即可,实现起来也不会有歧义,__setitem__方法实现需要先进行分割,然后递归进行即可。但是__getattr__的实现也是很简单,直接递归查询即可。但是__setattr__就不是了,因为在 set 前会先调用 get 方法来进行查询,如果不存在

最后解决文件 IO 的问题。

handler方面,为喜欢自定义的用户提供了注册器,可以直接将自定义的handler注册到包中,或者将自定义的文件格式使用已有的handler进行解析。

Roadmap

目前项目进行到了v0.0.1版本,经过了 3 个pre-release版本。

但是肉眼可见的存在一些问题。

首先是目前还不支持数据类型的转换,默认的参数可能只能通过预先入读默认文件或者预先转换argparse的形式来实现,在pyini文件的接口还有待优化,目前都是 hard code 了名称。

Takeaways

说实话,这个项目确实让我了解了很多配置文件的格式及各自特点,已经 Python 的内置函数和内置函数的调用顺序,比如__setattr__会先调用 __getattr__ 但是并不是在 __setattr__ 中实现的,而是在更高一级实现,所以需要做好处理。

除此之外,更为重要的是方便我自己的项目配置文件书写吧,毕竟很可能没什么人会用 hhh