需求
需要对比 nacos 两套环境之间的 yaml 文件差异性时,每套环境中有的数个文件,其中文件数量、文件名称、相同文件有不通内容,需要将差异性列出来。
实现方案
方案1:一个一个文件的用本地工具或在线工具进行对比,比如 Beyond Compare、Idea 对比文件
方案2:当多个环境之前,比如开发,测试,仿真,生产 反复多次对比时,方案1的一次性会体现出重复性的工作,所以可以自己写脚本来对比
先读取 yaml 目录,解析 yaml 文件为 json(python 模块 yaml)
通过 json 结构,解析对比不同的属性值(python模块 json_tools:http://www.ibloger.net/article/3518.html)
实现代码
# !/usr/bin/env python3 # -*- coding: utf-8 -*- import os.path import yaml import json_tools """ json 比较工具 将读取的字符串类型转化为字典或列表,loader可以选择以下几种: - BaseLoader:仅加载最基本的YAML - SafeLoader:安全地加载YAML语言的子集。建议用于加载不受信任的输入。(safe_load) - FullLoader:加载完整的YAML语言。避免任意代码执行。这是当前(PyYAML 5.1)默认加载器调用yaml.load(input)(发出警告后)(full_load) - UnsafeLoader(也称为Loader向后兼容性):原始的Loader代码,可以通过不受信任的数据输入轻松利用。 """ def abbr_txt(data): if isinstance(data, str) and len(data) > 90: return data[:90] + '...'; else: return data if __name__ == '__main__': prefix = 'files/' source = 'aaa' target = 'bbb' f_name_list = os.listdir(prefix + source) t_files = os.listdir(prefix + target) ignore_files = [] # ignore_files = ['CAE-AUTHORIZATION.yaml'] no_yml_file = list() s_diff_files = set(f_name_list) - set(t_files) if s_diff_files: print(target, '不存在的文件', s_diff_files) same_files = set(f_name_list) & set(t_files) if same_files: print(target, '共存的文件', same_files) print('\n-----------------------\n') for f_name in sorted(same_files): if 'yaml' in f_name or 'yml' in f_name: if f_name in ignore_files: continue s_stream = open(prefix + source + '/' + f_name, mode='r', encoding='utf-8') t_stream = open(prefix + target + '/' + f_name, mode='r', encoding='utf-8') s_data = yaml.load(s_stream, Loader=yaml.FullLoader) t_data = yaml.load(t_stream, Loader=yaml.FullLoader) s_stream.close() t_stream.close() if s_data == t_data: # print(f_name, '内容一致') pass else: print('{}内容不一致'.format(f_name)) s_miss_dict, t_miss_dict = {}, {} s_diffKey, t_diffKey = {}, {} for diff in json_tools.diff(s_data, t_data): t_missKey = dict(diff).get('remove') s_missKey = dict(diff).get('add') diffKey = dict(diff).get('replace') value = dict(diff).get('value') prev = dict(diff).get('prev') # print(diff) if t_missKey: t_miss_dict[t_missKey] = prev if s_missKey: s_miss_dict[s_missKey] = value if diffKey: s_diffKey[diffKey] = prev t_diffKey[diffKey] = value if t_miss_dict: print('\n{} 缺失'.format(target)) for k, v in t_miss_dict.items(): print(' ', k, '=', v) if s_miss_dict: print('\n', source, '缺失') for k, v in s_miss_dict.items(): print(' ', k, '=', v) if s_diffKey: print('\n属性值不同') for k, v in s_diffKey.items(): print(' ', k, '\n 「{} -> {}」:{} -> {}'.format(source, target, abbr_txt(v), abbr_txt(t_diffKey.get(k)))) else: no_yml_file.append(f_name) if no_yml_file: print('\n非yml文件', no_yml_file)
对比结果
bbb 不存在的文件 {'AFFILIATE-MARKETING.yaml', 'logback.xml', '_legacy_quartz.yaml'} bbb 共存的文件 {'CAE-GATEWAY.yaml'} ----------------------- CAE-GATEWAY.yaml内容不一致 bbb 缺失 /server/connection-timeout = 10000ms /spring/cloud/gateway/routes/1 = {'id': 'service', 'uri': 'lb://SERVICE', 'predicates': ['Path=/service/**'], 'filters': ['StripPrefix=1', {'name': 'Retry', 'args': {'retries': 3, 'statuses': ['INTERNAL_SERVER_ERROR'], 'methods': ['GET', 'POST'], 'series': ['SERVER_ERROR']}}]} aaa 缺失 /spring/cloud/gateway/routes/0/filters/1 = {'name': 'Retry', 'args': {'retries': 3, 'statuses': ['INTERNAL_SERVER_ERROR'], 'methods': ['GET', 'POST'], 'series': ['SERVER_ERROR']}} 属性值不同 /server/tomcat/background-processor-delay 「aaa -> bbb」:30s -> 60s /spring/cloud/gateway/routes/0/id 「aaa -> bbb」:MEMBER-CENTER -> service /spring/cloud/gateway/routes/0/uri 「aaa -> bbb」:http://MAGIC-MEMBER:8080 -> lb://SERVICE /spring/cloud/gateway/routes/0/predicates/0 「aaa -> bbb」:Path=/MEMBER-CENTER/** -> Path=/service/**
未经允许请勿转载:程序喵 » Python 对比两组 yaml 文件的差异性