前言
最近工作和生活上比较忙,都没时间研究黑科技了(其实把玩游戏的时间挤出点来也就够了,不过不可能的),今天来水一篇,不对,更新一个常见配置文件格式对比以及使用方法。
常用的配置文件有这几种,最简单的Properties配置文件、经典的ini配置文件、依然保留一亩三分地的xml配置文件、在数据交换领域大显身手的json配置文件、以及充满野心的YAML配置文件等。
一个优秀的配置文件格式应该包含以下几个要素:
- 规则简单
- 可读性好
- 支持层级关系
- 允许注释
- 易于解析
- 逐行解析
- 支持列表和字典
- 支持多种数据类型
下面根据这几个要素分析一下它们的优劣和具体使用方法。
Properties
.properties 主要用在 JAVA 程序中,JAVA 内置对它的解析。它是一种简单的配置文件格式,规则大概只有下面几条:
- 使用
= :
或者空格作为键值对的分隔符; - 单引号和双引号会作为值的一部分;
- 允许使用
#
作为注释; - 可以使用
\
作为转义符,用来转义空格、换行和 Unicode 编码。
因为如此简单的格式,properteis 基本上不需要进行任何解释就能直接使用。也正因为它如此简单,不支持层级关系,因此它并不能算做好的配置文件 。
INI
INI相当于扩展版本的 properties ,包含 properties 的所有优点,去除了一些缺点,并且可以使用 section 来支持层级。它与 .properties 的主要区别如下:
- 支持 [section];
- 不使用空格作为分隔符;
- 允许在键名和值中直接包含空格(不需使用转义符);
- 支持更多的转义符。
综上,INI 格式是好的配置文件。
在Windows系统中,经常使用INI 文件作为系统或者第三方软件的配置文件,当然INI文件 的后缀名也不一定是”.ini”也可以是”.cfg”,”.conf ”或者是”.txt”。
格式
INI文件的格式很简单,最基本的三个要素是:parameters,sections 和 comments。
最基本的“元素”就是parameter也就是键值对,每一个parameter都有一个name和一个value,name和value由等号“=”隔开,name在等号的左边。
而所有的parameters都是以sections为单位结合在一起的。所有的section名称都是独占一行,并且sections名字都被方括号包围着。在section声明后的所有parameters都是属于该section。对于一个section没有明显的结束标志符,一个section的开始就是上一个section的结束。
comments也就是注释,是以分号“;”开始的。所有的注释语句不管多长都是独占一行直到结束的。在分号和行结束符之间的所有内容都是被忽略的。
读写示例
下面是一个简单的INI文件。
[mysql] ;这是IP host = localhost ;这是端口 port = 3307
使用Python读写INI文件的方式如下:
import configparser import os def readConf(): '''读取配置文件''' conf = configparser.ConfigParser() conf.read('test.conf') # 文件路径 properties = conf.items("mysql") print(properties) name = conf.get("mysql", "host") # 获取指定section 的option值 print(name) def writeConf(): '''写入配置文件''' conf = configparser.RawConfigParser() if not conf.has_section("mongodb"): conf.add_section("mongodb") if not conf.has_option("mongodb", "port"): conf.set("mongodb", "port","27777") with open("test.conf", "w") as confFile: conf.write(confFile)
JSON
由于 JavaScript 的流行,JSON 当然成了最适合 JavaScript 使用的配置文件。JSON 可以在 JavaScript 中使用 eval()
或者 JSON.parse()
来解析,解析后的内容直接成为 JavaScript 的内置对象。
但是,其实 JSON 不适合作为配置文件使用。根据上面的要素来看,JSON 规则简单但不易读(尤其是复杂的没有格式化过的 JSON),不支持注释,也不能使用较为宽松的语法,严格的格式规范下逐行解析就别想了。
JSON 的确是在网页和 API 中传递信息的一种好格式,而且各种语言都有它的解析库,很多开源工具也喜欢使用JSON做为配置文件,但显然并不是很适合做配置文件。
格式
JSON格式是基于列表和字典的,同样是通过键值对来记录数据,而值可以使子级的列表或者字典对象,从而可以实现复杂的嵌套关系。
读写实例
Python可以使用json库读写JSON格式,也可以使用pickle库进行处理。
区别是使用json库可以在不同语言之间交换数据的,而pickle库只在python之间使用。json库只能把常用的数据类型序列化(列表、字典、列表、字符串、数字),比如日期格式、类对象json就不行了。而pickle可以序列化所有的数据类型,包括类,函数都可以序列化。
首先是一个简单的JSON文件。
{ "name": "yumefx", "age": 3, "labels": [ { "labelName": "赌狗", "labelID": 1 }, { "labelName": "铳王", "labelID": 2 } ] }
下面以json库为例,对JSON文件进行读写。
import json import os def readJson(): '''读取配置文件''' with open("test.json", 'r') as load_f: load_dict = json.load(load_f) # 读取成Dict print(load_dict) def writeJson(): '''写入配置文件''' save_dict = {"name":""} with open("test.json", 'w') as save_f: json.dump(save_dict,save_f) # Dict写入 # Dict转str print(json.dumps({"name":["yumefx", "rick", "morty"]})) # str转Dict print(json.loads('{"name":["yumefx", "rick", "morty"]}'))
XML
XML是可扩展标记语言,格式类似HTML,虽然是好的配置文件格式 ,但它编辑起来太麻烦。即使是有 XML Notepad 这类软件的存在,太多的尖括号和嵌套也让手写这种配置文件变得艰难且更容易出错。
但很多软件的配置文件依然是基于XML的,因此依然有着一定的使用频率。
格式
XML的格式是基于XML元素的,元素包括起始标签、属性、内容以及结束标签,元素之间可以并列或者嵌套。
在HTML中,某些标签可以省略结束标签,而在XML中所有元素必须有结束标签;XML必须有根标签;XML的属性值必须使用引号包裹;标签不能以数字或标点符号开头,并且不能包含空格。
读写实例
一个简单的XML文件内容如下。
<?xml version='1.0' encoding='utf-8'?> <note> <!--你瞅啥--> <name language="ENU">yumefx</name> <status>sleeping</status> </note>
在Python中常见的XML编程接口有DOM和SAX,这两种接口处理XML文件的方式不同,使用场合也不同。python有三种方法解析XML:SAX,DOM和ElementTree。
其中SAX用的是事件驱动模型,通过在解析XML过程中触发一个个的事件并调用用户定义的回调函数来处理XML文件。这是一种流式处理,一边读一边解析,占用内存少。适合读取大文件或者只读取部分内容的场景。
DOM则是在解析一个XML文档时,一次性读取整个文档,把文档中所有元素保存在内存中的一个树结构里,之后利用DOM提供的不同函数来读取该文档的内容和结构,也可以把修改过的内容写入XML文件。考虑到性能,只适合读取一些简单的配置文件。
ElementTree则是一个轻量级的DOM,具有方便友好的API。代码可用性好,速度快,消耗内存少。
下面以ElementTree模式对XML文件进行读写。
from xml.etree import ElementTree as ET def readXML(): '''读取配置文件''' # 打开xml文档,读取内容为str str_xml = open('test.xml', 'r').read() # 将字符串解析成xml特殊对象,root代指xml文件的根节点 root = ET.XML(str_xml) # 或者直接解析XML文件成xml对象 # tree = ET.parse("test.xml") # root = tree.getroot() for child in root: print(child.tag, child.attrib) def writeXML(): '''写入配置文件''' root = ET.Element("famliy") son1 = ET.SubElement(root, "son", attrib={'name': 'child1'}) son2 = ET.SubElement(root, "son", attrib={"name": "child2"}) grandson1 = ET.SubElement(son1, "age", attrib={'name': 'grandChild11'}) grandson1.text = 'morty' et = ET.ElementTree(root) et.write("test.xml", encoding="utf-8", xml_declaration=True, short_empty_elements=False)
那么,有没有比较完美的配置文件格式呢?
有的,那就是XML的进化版YAML,篇幅所限,且听下回分解。
爱任何事物的方法,
就是要意识到你可能会失去它。
——G.K.切斯特顿
评论
921256 60898Thankyou for all your efforts which you have put in this. extremely fascinating info . 654976
999680 331083Really instructive and great structure of content material material , now thats user friendly (:. 637245