雅美尓(yaml)实战
献给跟我一样对yaml(雅美尓)有婶婶挫败感的同学!
开始第一个pylon工程,我们就跟yaml配置文件开始了不解之缘。yaml是什么?它有哪些规则?
大IBM的文章如是说:YAML 是一种比 XML 更为简单易读的序列化语言。Structure通过空格来展示,Sequence里的项用"-"来代表,Map里的键值对用":"分隔. 这几乎就是所有的语法了.
真的是这样简单吗?发布上线项目rigger却告诉我们mysql host没配置,配好再上线发现DOMAIN_PREFIX没配置,更一头雾水的是yaml里的各种符号" ! & * << ",看不懂,只能小心翼翼如履薄冰Ctrl+c , Ctrl+v,Ctrl+c , Ctrl+v ....
本文试图让你完全理解如下配置sample.yaml,并能通过一个小程序解析这个配置。需要大家动手跑一跑python程序,10分钟后,就再也不怕yaml的BT标记了。
5分钟workshop
sample.yaml:
reusable: - !R.vars &common_setting REDIS_PORT: 16379 BETA_REDIS: 6 ONLINE_REDIS: 7 GIT_PATH: "/usr/local/bin/git" PHP_ERROR: "E_ERROR" SDK_PATH: "/home/q/php/plato_sdk/" CONFSVC_URL: "plato.svc.1360.com" XHPROF: "OFF" - !R.vars &sdk_deploy pkg : "pkg" name : "plato_sdk" root : "./sdk" __env: cache: !R.env res: - !R.vars debug: !R.vars &debug_support PHP_ERROR: "E_ALL & ~E_NOTICE" DEBUG: "ON" PYL_LOG_MODE: "DEBUG" dev: !R.env res: - !R.using refs: - *common_setting - *debug_support - !R.vars ENV: "dev" DOMAIN_PREFIX: "${USER}." beta_sdk: !P.publish <<: *sdk_deploy host: "127.0.0.1" |
现在看到了这样一个文件,怎么读懂它?处理它?
基本语法:
- 列表 : 哈希对 & 表示一个 "锚点标记" ,其它节点可以使用 "*" 或 "<<: *" 来引用它的值 * 引用,指node4的内容与node3完全一致 <<: * 的作用,指node5的内容包含但不完全相同于node3的值。 ! tag标记,可以注册自己指定的类型 |
语法知道了,怎么解析?下面来一个简单易懂小例子, 为了省事儿,yaml.add_multi_constructor(u"!R.env", construct_object) 用map指代 !R.xxx 代表的自定义类
yaml_simple.py :
import sys import yaml from yaml import load, dump def construct_object(loader, suffix, node): return loader.construct_yaml_map(node) yaml.add_multi_constructor(u "!R.env" , construct_object) yaml.add_multi_constructor(u "!P.publish" , construct_object) yaml.add_multi_constructor(u "!R.using" , construct_object) yaml.add_multi_constructor(u "!P.pkg" , construct_object) yaml.add_multi_constructor(u "!R.vars" , construct_object) txt = file( "sample.yaml" ).read() data = load(txt) print data print data[ '__env' ][ 'dev' ][ 'res' ][ 0 ][ 'refs' ][ 0 ][ 'SDK_PATH' ] |
找台测试服务器,把两个文件放上去,命令行执行:python yaml_simple.py
输出:
{ 'beta_sdk' : { 'host' : '127.0.0.1' , 'root' : './sdk' , 'pkg' : 'pkg' , 'name' : 'plato_sdk' }, '__env' : { 'debug' : { 'DEBUG' : 'ON' , 'PHP_ERROR' : 'E_ALL & ~E_NOTICE' , 'PYL_LOG_MODE' : 'DEBUG' }, 'cache' : { 'res' : [{ 'API_PROXY' : 'http://127.0.0.1:8086' }]}, 'dev' : { 'res' : [{ 'refs' : [{ 'SDK_PATH' : '/home/q/php/plato_sdk/' , 'ONLINE_REDIS' : 7 , 'BETA_REDIS' : 6 , 'GIT_PATH' : '/usr/local/bin/git' , 'CONFSVC_URL' : 'plato.svc.1360.com' , 'PHP_ERROR' : 'E_ERROR' , 'REDIS_PORT' : 16379 , 'XHPROF' : 'OFF' }, { 'DEBUG' : 'ON' , 'PHP_ERROR' : 'E_ALL & ~E_NOTICE' , 'PYL_LOG_MODE' : 'DEBUG' }]}, { 'DOMAIN_PREFIX' : '${USER}.' , 'ENV' : 'dev' }]}}, 'reusable' : [{ 'SDK_PATH' : '/home/q/php/plato_sdk/' , 'ONLINE_REDIS' : 7 , 'BETA_REDIS' : 6 , 'GIT_PATH' : '/usr/local/bin/git' , 'CONFSVC_URL' : 'plato.svc.1360.com' , 'PHP_ERROR' : 'E_ERROR' , 'REDIS_PORT' : 16379 , 'XHPROF' : 'OFF' }, { 'root' : './sdk' , 'pkg' : 'pkg' , 'name' : 'plato_sdk' }]} /home/q/php/plato_sdk/ |
5分钟进阶
YAML(IPA: /ˈjæməl/,尾音类似camel骆驼)是一个可读性高,用来表达资料序列的格式。
YAML是"YAML Ain't a Markup Language"(YAML不是一种置标语言)的递回缩写。在开发的这种语言时,YAML 的意思其实是:"Yet Another Markup Language"(仍是一种置标语言),但为了强调这种语言以数据做为中心,而不是以置标语言为重点,而用返璞词重新命名。
以下为可能用到的各种符号的解释和示例:
--- # # > 的作用,以缩进对齐来判断是否为一段文字,也就是说,一旦缩进与上一行不一致,则认为是一个新行。 # node1的例子中,第一行 "Ther... door" , # 第二行 " " Please... floor "" , # 第三行 "So...So2" node1: > Ther once was a man from Darjeeling Who got on a bus bound for Ealing It said on the door "Please don't spit on the floor" So he carefully spat on the ceiling So2 # | 的作用,它表示之后的文字,每一行均为一个新行。 node2: | Ther once was a man from Darjeeling Who got on a bus bound for Ealing It said on the door "Please don't spit on the floor" So he carefully spat on the ceiling # & 的作用,它表示一个 "锚点标记" ,其它节点可以使用 "*" 或 "<<: *" 来引用它的值 node3: &node3 a: 001 b: 002 # * 的作用,指node4的内容与node3完全一致 node4: *node3 # <<: * 的作用,指node5的内容包含但不完全相同于node3的值。 node5: <<: *node3 c: 003 # !! 的作用,强迫转换类型。 #输出: #{ "node6" =>{ # "a" =>#<YAML::PrivateType: 0x9df6d40 @value = "123" , @type_id = "float" >, # "b" =>#<YAML::PrivateType: 0x9df6ae8 @value = "true" , @type_id = "str" >, # "c" => true #} #注意:c的值为布尔型。 node6: a: !! float 123 b: !!str true c: True # 二进制内容的表示 node7: !!binary | xxxxxxxxxxxxx xxxxxxxxx xxxxx node8_value: &node8_value {id: 10000 , code: item_manager, name: 项目经理} #自定解析类型,YAML某Key的Value一般为Array或Hash,但如果需要将Value解析为其它的自定义类型,可以使用该方法。 #步骤: # 1 、首先定义 MyCustClass 类,如: # class MyCustClass # attr_accessor :id # attr_accessor :code # def initialize v_hash # @id = v_hash[ "id" ] # @code = v_hash[ "code" ] # end # end # 2 、向YAML注册解释类型,如: # YAML::add_domain_type( "yaml.org,2002" , 'MyCustClass' ) do |type, val| # MyCustClass. new (val) # end # 3 、OK,当YAML文件加载时,YAML将自动将 "node8" 的值解析为MyCustClass类型。 # 4 、测试一下,x[ "node8" ] >> #<MyCustClass: 0x9df1c88 @code = "item_manager" , @id = 10000 > # x[ "node8" ].code >> "item_manager" node8: !MyCustClass <<: *node8_value # ? 的作用,用来明确的表示多个词汇组成的键值 # a[ "node9" ] => {{ "a" => 1 , "b" => 2 }=>[ 1 , 2 ], "c" => 3 } node9: ? {a: 01 , b: 02 } : [ 1 , 2 ] c: 3 |
want more?
有兴趣的同学可以进一步了解rigger源码,会发现诸如!P.publish、!R.using,其实都是写的一个python类,会有自定义的属性,所以某些属性未定义,就会报错了。更有兴趣的可以把 yaml_simple.py 扩展为小工具,结合rigger,随时检查自己的配置文件是否有错误。
推荐yaml在线验证工具 https://yaml-online-parser.appspot.com/ 可以提前发现格式问题,but 要FQ,FQ设置见附录。
yaml提示不够友好,对齐错误有可能提示为“yaml.parser.ParserError: while parsing a block mapping“ ” expected <block end>, but found '<block mapping start>' 需要小心注意
总结
为什么不是XML呢?因为:
- YAML的可读性好。
- YAML和脚本语言的交互性好。
- YAML使用实现语言的数据类型。
- YAML有一个一致的信息模型。
- YAML易于实现。
上面5条也就是XML不足的地方。同时,YAML也有XML的下列优点:
- YAML可以基于流来处理;
- YAML表达能力强,扩展性好。
总之,YAML试图用一种比XML更敏捷的方式,来完成XML所完成的任务。当然简单的工具用深入之后就成了开篇那种样子,门槛有点高,但也体现深入研究一个小玩意的有趣之处。
参考文章:
http://zh.wikipedia.org/wiki/YAML
http://www.ibm.com/developerworks/cn/xml/x-cn-yamlintro/
http://www.yaml.org/spec/1.2/spec.html
http://pyyaml.org/wiki/PyYAMLDocumentation
http://sqycyl.iteye.com/blog/859589
雅美尓(yaml)实战的更多相关文章
- 《1Q84》--[日]村上春树
<1Q84>,作者是:村上春树(村长) 故事梗概: 1984年,青豆与天吾皆为30岁,青豆为健身教练但另一面则是暗杀者,将受到极度暴力 的妇女们的丈夫们送至死亡的世界.天吾的职业为升大学的 ...
- 解决Javascript大数据列表引起的网页加载慢/卡死问题。
在一些网页应用中,有时会碰到一个超级巨大的列表,成千上万行,这时大部份浏览器解析起来就非常痛苦了(有可能直接卡死). 也许你们会说可以分页或动态加载啊?但是有可能需求不允许分页,动态加载?网络的延迟也 ...
- Disjoint Sets
Disjoint Sets Disjoint Sets的意思是一堆集合們,它們相互之間都沒有交集.沒有交集是指:各個集合之間沒有擁有共同.相同的元素.中文稱作「分離集」. Disjoint Sets的 ...
- 线程进阶:多任务处理(17)——Java中的锁(Unsafe基础)
在网络层,互联网提供所有应用程序都要使用的两种类型的服务,尽管目前理解这些服务的细节并不重要,但在所有TCP/IP概述中,都不能忽略他们: 无连接分组交付服务(Connectionless Packe ...
- Python识别璇玑图中诗的数量
一.璇玑图简介 璇玑图的读法有很多,这里我使用七七棋盘格的读法,在璇玑图中分离出一个七七棋盘格,如下表 吏 官 同 流 污 合 玩 痞 悍 蒙 骗 造 假 蛋 鸡 宴 请 客 友 朋 远 戚 偏 正 ...
- 利用Javascript解决HTML大数据列表引起的网页加载慢/卡死问题。
在一些网页应用中,有时会碰到一个超级巨大的列表,成千上万行,这时大部份浏览器解析起来就非常痛苦了(有可能直接卡死). 也许你们会说可以分页或动态加载啊?但是有可能需求不允许分页,动态加载?网络的延迟也 ...
- Java开发者职业生涯要看的200+本书
作者:老刘链接:https://www.zhihu.com/question/29581524/answer/684872838来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...
- 最强 Java 书单推荐,附学习方法
技术大佬用1w+字来告诉你该读什么书,循序渐进,并提供百度云盘下载地址.重要的是还有学习方法. 请肆无忌惮地点赞吧,微信搜索[沉默王二]关注这个在九朝古都洛阳苟且偷生的程序员.本文 GitHub gi ...
- 本溪6397.7539(薇)xiaojie:本溪哪里有xiaomei
本溪哪里有小姐服务大保健[微信:6397.7539倩儿小妹[本溪叫小姐服务√o服务微信:6397.7539倩儿小妹[本溪叫小姐服务][十微信:6397.7539倩儿小妹][本溪叫小姐包夜服务][十微信 ...
随机推荐
- jQ中对attr()方法的理解
在JS中设置节点的属性与属性值用到setAttribute(),获得节点的属性与属性值用到getAttribute(),而在jquery中,用一个attr()就可以全部搞定了,赞一个先 ^^jquer ...
- 大白的webservice
1.什么是web服务: web服务是一种可以用来解决跨网络应用集成问题的开发模式,这种模式为实现"软件即服务"提供了技术保障. 2.web服务的三个核心 (SOAP,WSDL,UD ...
- 《利用python进行数据分析》读书笔记 --第一、二章 准备与例子
http://www.cnblogs.com/batteryhp/p/4868348.html 第一章 准备工作 今天开始码这本书--<利用python进行数据分析>.R和python都得 ...
- C++多线程の线程通信future,promise,async
- easyui-window 关闭事件,只要关闭窗口就会触发
$(function () { $('#windowsMSG').window({ onBeforeClose: function () { //当 ...
- 简单介绍一下R中的几种统计分布及常用模型
统计学上分布有很多,在R中基本都有描述.因能力有限,我们就挑选几个常用的.比较重要的简单介绍一下每种分布的定义,公式,以及在R中的展示. 统计分布每一种分布有四个函数:d――density(密度函数) ...
- 复旦大学2015--2016学年第二学期高等代数II期末考试情况分析
一.期末考试成绩班级前几名 胡晓波(90).杨彦婷(88).宋卓卿(85).唐指朝(84).陈建兵(83).宋沛颖(82).王昊越(81).白睿(80).韩沅伯(80).王艺楷(80).张漠林(80) ...
- USB OTG插入检测识别
转载请标注原文地址:http://blog.csdn.net/uranus_wm/article/details/9838847 一 USB引脚一般四根线,定义如下: 为支持OTG功能,mini/mi ...
- 3d游戏模型及地形提取及导航
支持所有DirectX的游戏模型提取 有需要的可以直接联系我!QQ290387340
- 连锁机构3D指纹考勤系统解决方案
信息技术的高速发展加速了商业零售业连锁经营的信息化和全球化的进程,同时也推动了商业管理的变革.尽管人们对它的认识是被动与滞后的,但这种变革依然伴随着商业业态的转变和信息技术的发展或快或慢地在悄然进行着 ...