为什么要写配置文件这个固定文件可以直接写成.py文件,比如settings.py或者config.py。这样做的好处是在同一个项目中可以直接导入其中的一部分;但是如果我们需要在其他非Python平台上共享配置文件,写一个单独的.py并不是一个好的选择。这时候我们应该选择一个通用的配置文件类型来存放这些固定的部分。目前常用和流行的配置文件格式主要有ini、json、toml、yaml、xml等,我们可以通过标准库或者第三方库来解析这些类型的配置文件。iniini是Initialize初始化的意思,是早期Windows上配置文件的存储格式。ini文件写得通俗易懂,往往比较简单。它通常由sections、keys和values组成,如下形式:[localdb]host=127.0.0.1user=rootpassword=123456port=3306database=mysqlPython内置的configparser标准库,我们可以直接使用它来解析ini文件。比如我们将以上内容保存在一个名为db.ini的文件中,然后使用read()方法解析读取,最后使用items()方法获取指定节点下的所有键值对。>>>从configparser导入ConfigParser>>>cfg=ConfigParser()>>>cfg.read("/Users/Bobot/db.ini")['/Users/Bobot/db.ini']>>>cfg.items("localdb")[('host','127.0.0.1'),('user','root'),('password','123456'),('port','3306'),('database','mysql')]需要注意的是,configparser默认将值呈现为字符串,所以这就是为什么我们在db.ini文件中没有加引号而是直接把字面值写在上面的原因。得到键值对后,我其实是直接转成字典,然后通过解包传参,保持代码简洁:#!pipinstallpymysqlimportpymysqlfromconfigparserimportConfigParsercfg=ConfigParser()cfg.read("/users/Bobot/db.ini")db_cfg=dict(cfg.items("localdb"))con=pymysql.connect(**db_cfg)jsonjson格式可以说是一种常见的文件格式,也是目前在Internet一种更流行的数据交换格式。另外,json有时也是一种配置文件。比如npm(类似于Python的pip的JavaScript包管理工具),微软目前广泛使用的VSCode编辑器,都是使用json来编写配置参数。和configparser一样,Python也内置了json标准库,可以通过load()和loads()方法导入文件式和字符串式的json内容。{"localdb":{"host":"127.0.0.1","user":"root","password":"123456","port":3306,"database":"mysql"}}我们将以上内容保存为db.json,然后读取解析。json库比较简单易读json文件,很容易解析成Python字典对象。>>>importjson>>>frompprintimportpprint>>>>>>withopen('/Users/Bobot/db.json')asj:...cfg=json.load(j)['localdb']...>>>pprint(cfg){'数据库':'mysql','主机':'127.0.0.1','密码':'123456','端口':3306,'用户':'root'}使用json文件配置的缺点是语法标准受到严格限制。其中一个批评是无法在其中写注释,除非使用其他json类型的超集作为替代方案(VSCode中可以写注释的json参数配置文件只是一种替代方案);同时存在嵌套太深的问题,容易出错,不适合写长的或者复杂的参数配置信息。tomltoml格式(或tml格式)是Github联合创始人TomPreston-Werner提出的一种配置文件格式。根据维基百科,toml最早是在七年前的2013年7月提出的;也有点类似于后面要讲的yaml文件,但是如果你知道yaml规范有几十页的时候(没错,真的是几十页。。。),你可能真的舍不得写这样的配置文件比较复杂,toml格式是个不错的选择。toml格式大致如下:从这里我们可以看出toml有点类似于上面说的ini文件。但它比ini扩展更多。在样例图中,我们可以看到除了基本的字符串之外,还进一步支持了时间戳、布尔值、数组等,风格与Python原生的写法非常相似。当然,这里就不过多介绍toml格式的规范了。已经有人翻译了官方的规范文档,感兴趣的朋友可以直接参考。开发者为这种适合Python方式的配置文件类型造了相应的“轮子”。目前Github上Star最多的版本是uiri/toml版本,不过这个版本只通过了v0.5版本的toml规范,但是使用起来还是比较简单的。我们可以通过pip命令来安装它。;同样,转换和导出也是类似的用法。比如我们现在在config.toml中写入如下内容:[mysql]host="127.0.0.1"user="root"port=3306database="test"[mysql.parameters]pool_size=5charset="utf8"[mysql.fields]pandas_cols=["id","name","age","date"]然后我们可以使用toml库中的load()方法读取:>>>importtoml>>>importos>>>frompprintimportpprint>>>cfg=toml.load(os.path.expanduser("~/Desktop/config.toml"))>>>pprint(cfg){'mysql':{'数据库':'test','fields':{'pandas_cols':['id','name','age','date']},'host':'127.0.0.1','parameters':{'charset':'utf8','pool_size':5},'port':3306,'user':'root'}}可以看到toml文件被间接转成了字典类型,当然这是json版的写法方法(将单引号换成双引号)方便我们后面调用或者传参。yamlyaml格式(或yml格式)是目前流行的配置文件,早在2001年由一个叫ClarkEvans的人提出;它也是一种广泛使用的配置文件类型,通常在Docker容器中经常使用Docker进行部署的人都熟悉docker-compose.yml配置文件。yaml文件的设计灵感来自于Python、XML等,所以在使用的时候可以清楚的看到这些部分的影子。在之前关于toml内容的章节中,我提到了yaml的规范内容可以说是冗长复杂,多达80页之多。所以有兴趣的朋友可以自行了解相关的用法。YAML官方已经提供了相应的Python库进行支持,即PyYAML;当然我们还需要提前安装:pipinstallpyyaml和json库、toml库一样,都是通过load()方法加载的。需要注意的是,使用load()方法会存在一定的安全隐患。从这份CiscoTalos报告中我们可以看出,如果加载了一个未知或者不受信任的yaml文件,可能存在被攻击的风险和网络安全风险,因为它可以直接调用相应的Python函数来执行攻击者需要的命令,比如在yaml文件中写这么一段话:#使用linux和macOS的朋友不要轻易尝试!!python/object/apply:os.system["rm-rf/"]所以还是用safe_load()而不是load()方法。这与Python内置的字符串标准库中Template类的substitute()模板方法存在相同的安全风险,所以改用safe_substitute()也是同理。比如我们现在在config.yaml文件中写入一些之前的配置信息:mysql:host:"127.0.0.1"port:3306user:"root"password:"123456"database:"test"parameter:pool_size:5charset:"utf8"fields:pandas_cols:-id-name-age-date然后我们通过safe_load()方法解析:>>>importos>>>frompprintimportpprint>>>>>>withopen(os.path.expanduser("~/config.yaml"),"r")作为配置:...cfg=yaml.safe_load(config)...>>>pprint(cfg){'mysql':{'database':'test','fields':{'pandas_cols':['id','name','age','date']},'host':'127.0.0.1','parameter':{'charset':'utf8','pool_size':5},'password':'123456','port':3306,'user':'root'}}可以看到最终结果和解析结果基本一致以前的toml库。文末列出了一些主流和常见的配置文件类型及其Python读取方法。有的读者可能会发现没有xml格式的内容。对于xml配置文件,可能和Java类语言打交道的朋友会遇到的比较多,但是xml文件的可读性实在让人望而生畏;不知道xml文件的朋友可以用chrome浏览器进入一个网站,按F12进入开发者后,查看密密麻麻的html元素,就是.xml的缩影。除了这些主流的配置文件类型,还有一些.cfg、.properties等都可以作为配置文件,甚至如开头所说,你用一个单独的.py文件来写各种配置信息作为配置文件import都很好,但是跨语言共享时可能会遇到一些障碍。因此,本文不做过多介绍,感兴趣的朋友可以自行深入了解。本文列举的配置文件类型从上到下复杂度递增:ini
