Python常见的配置文件写法梳理汇总

AI 摘要 / TL;DR

关于Python,相比大家都不会陌生吧,那么,其中的一些配置文件是什么呢?有没有可能给大家去进行做一个汇总,汇总的内容还是比较的多的,包含写法等一些相关的知识,具体的一些相关汇总,下面给大家详细解答下。 前言 在这篇文章里所提到的环境变量种类其多元性由上至下到另一个先后提升:ini为何要写环境变量 在研发流程中,很多人

来源: https://www.ucloud.cn/yun/128439.html 作者: 89542767 发布日期: 发布于2022-12-19 20:41

关于Python,相比大家都不会陌生吧,那么,其中的一些配置文件是什么呢?有没有可能给大家去进行做一个汇总,汇总的内容还是比较的多的,包含写法等一些相关的知识,具体的一些相关汇总,下面给大家详细解答下。

前言

  在这篇文章里所提到的环境变量种类其多元性由上至下到另一个先后提升:ini为何要写环境变量

  在研发流程中,很多人都会使用一些固定不动主要参数或者整型变量。对于这类相对固定不动且经常使用的一部分,通常会把它提到一种固定不动文档中,防止在不同控制模块编码中反复发生进而维持核心内容编码干净整洁。

  这一个固定不动相关文件大家能直接写出一种.py文件,比如settings.py或config.py,如此的好处是可以在同一个工程下先通过import来导进中的一部分;那如果我们应该在其他非Python的平台配置文档共享时,写出多带带.py也不是一个好的选择。这时候我们就要挑选常用的环境变量种类来作存放这些固定一部分。现阶段常见且时兴配置文件类型种类关键有ini、json、toml、yaml、xml等,这些类型的环境变量大家都可以通过标准库或第三方库来进行解析。

  ini

  ini即Initialize初始化之意,早期是在Windows上配置文件的存储格式。ini文件的写法通俗易懂,往往比较简单,通常由节(Section)、键(key)和值(value)组成,就像以下形式:

  [localdb]
  host=127.0.0.1
  user=root
  password=123456
  port=3306
  database=mysql

  Python本身内置的configparser标准库,我们直接就可以用来对ini文件进行解析。如我们将上述内容保存在一个名为db.ini的文件中,然后使用read()方法来进行解析和读取,最后通过items()方法来获取指定节点下的所有键值对。

  >>>from configparser import 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')]

  json

  json格式可以说是我们常见的一种文件形式了,也是目前在互联网较为流行的一种数据交换格式。除此之外,json有时也是配置文件的一种。

  比如npm(JavaScript包管理工具类似Python的pip)、以及微软出品的目前被广泛使用的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的字典对象。

  >>>import json
  >>>from pprint import pprint
  >>>
  >>>with open('/Users/Bobot/db.json')as j:
  ...cfg=json.load(j)['localdb']
  ...
  >>>pprint(cfg)
  {'database':'mysql',
  'host':'127.0.0.1',
  'password':'123456',
  'port':3306,
  'user':'root'}

  使用json文件配置的缺点就是语法标准严格限制,为人所诟病之一的就是无法在当中写注释,除非采取json类型的其他超集作为替代方案(VSCode中能写注释的json参数配置文件便是代替方案的一种);同时存在嵌套过深的问题,容易导致出错,不宜用来写过长或复杂的参数配置信息。

  toml

  toml格式(或tml格式)是Github联合创始人Tom Preston-Werner所提出的一种配置文件格式。根据维基百科的资料,toml最开始提出时是在2013年7月份,距今已有七年时间;它在某些方面也与后面要谈到的yaml文件有些类似,但如果当你知道yaml的规范有几十页(没有错,真的就是几十页……)的时候,可能你真的就不太愿意去写那么复杂的配置文件,toml格式则倒是个不错的选择。

  toml格式大致如下:

01.png

  从这里可以看出toml有点类似于前面所讲的ini文件。但是它比ini扩展了更多的内容。

  在样例图片中我们可以看到,除了基本的字符串以外,例如时间戳、布尔值、数组等都进一步支持,而且样式和Python的原生写法十分类似。

  当然这里不会过多介绍toml格式的一些规范说明,有人已经对官方的规范文档进行了翻译,有兴趣的朋友可以直接查阅。

  这么契合Python方式的配置文件类型已经有开发者造出了相应的「轮子」,目前在Github上Stars数最多的是则是uiri/toml的版本,不过该版本仅通过了v0.5版本toml规范,但在使用上还是蛮简洁的,我们可以通过pip命令进行安装

  pip install toml

  该库的解析方式很简单,也有点类似于json库的解析用法,即通过load()或loads()来进行解析;同理转换并导出也是同样类似的用法。

  比如我们现在将以下内容写入到config.toml中:

  [mysql]
  host="127.0.0.1"
  user="root"
  port=3306
  database="test"
  [mysql.parameters]
  pool_size=5
  charset="utf8"
  [mysql.fields]
  pandas_cols=["id","name","age","date"]

  紧接着我们就可以通过toml库中的load()方法来进行读取:

  >>>import toml
  >>>import os
  >>>from pprint import pprint
  >>>cfg=toml.load(os.path.expanduser("~/Desktop/config.toml"))
  >>>pprint(cfg)
  {'mysql':{'database':'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版的写法(将单引号替换成双引号即可),方便我们后续调用或者传参。

  yaml

  yaml格式(或yml格式)是目前较为流行的一种配置文件,它早在2001由一个名为Clark Evans的人提出;同时它也是目前被广泛使用的配置文件类型,典型的就是Docker容器里的docker-compose.yml配置文件,如果经常使用Docker进行部署的人对此不会陌生。

  yaml文件的设计从Python、XML等地方获取灵感,所以在使用时能很清楚地看到这些部分的影子。

  在上一节toml内容里我曾提到,yaml的规范内容可以说是冗长和复杂,足足有80页之多(斗尊强者,恐怖如斯……)。

  yaml规范页数:

  所以感兴趣的朋友可以再自行了解相关用法。

  YAML官方早已经提供了相应的Python库进行支持,即PyYAML;当然也同样需要我们事先进行安装:

  pip install pyyaml

  同json库和toml库一样,通过load()方法来进行加载。

  需要注意的是,使用load()方法会存在一定的安全隐患,从思科Talos的这份报告中我们可以看到,如果加载了未知或不信任的yaml文件,那么有可能会存在被攻击的风险和网络安全隐患,因为它能够直接调用相应的Python函数来执行为攻击者所需要的命令,比如说在yaml文件中写入这么一段:

  #使用Linux和macOS的朋友不要轻易尝试

  !!python/object/apply:os.system["rm-rf/"]

  因此最好是使用safe_load()来代替load()方法。

  这和Python内置的string标准库中Template类的substitute()模板方法一样存在着同样的安全隐患,所以使用safe_substitute()来替代是一样的道理。

  如我们现在将之前的一些配置信息写入config.yaml文件中:

  mysql:
  host:"127.0.0.1"
  port:3306
  user:"root"
  password:"123456"
  database:"test"
  parameter:
  pool_size:5
  charset:"utf8"
  fields:
  pandas_cols:
  -id
  -name
  -age
  -date
  然后我们通过safe_load()方法进行解析:
  >>>import os
  >>>from pprint import pprint
  >>>
  >>>with open(os.path.expanduser("~/config.yaml"),"r")as config:
  ...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文件来书写各类配置信息作为配置文件进行导入都是没问题,只是在跨语言共享时可能会有些障碍。因此本文就不过多介绍,感兴趣的朋友可以进一步自行了解。

  在本文里列举的配置文件类型其复杂性由上到下依次增加:ini<json≈toml<yaml,它们之间各有优劣,可以根据自己实际的需求和团队协作要求来具体选择。