Python脚本如何合并多份配置文件

wen python案例 27

本文目录导读:

Python脚本如何合并多份配置文件

  1. 简单拼接(适用于相同格式的配置文件)
  2. 合并JSON配置文件
  3. 合并INI配置文件
  4. 合并YAML配置文件
  5. 智能合并(支持优先级)
  6. 命令行工具版本
  7. 使用建议

我来介绍几种合并配置文件的方法,从简单到进阶:

简单拼接(适用于相同格式的配置文件)

def merge_config_files_simple(file_list, output_file):
    """简单拼接多个配置文件"""
    with open(output_file, 'w', encoding='utf-8') as outfile:
        for fname in file_list:
            with open(fname, 'r', encoding='utf-8') as infile:
                outfile.write(infile.read())
                outfile.write('\n')  # 添加换行符
# 使用示例
files = ['config1.ini', 'config2.ini', 'config3.ini']
merge_config_files_simple(files, 'merged_config.ini')

合并JSON配置文件

import json
import glob
def merge_json_configs(config_files):
    """合并多个JSON配置文件"""
    merged_config = {}
    for file_path in config_files:
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                config = json.load(f)
                # 递归合并配置
                merged_config = deep_merge(merged_config, config)
        except FileNotFoundError:
            print(f"文件不存在: {file_path}")
        except json.JSONDecodeError:
            print(f"JSON格式错误: {file_path}")
    return merged_config
def deep_merge(base, override):
    """深度合并字典"""
    merged = base.copy()
    for key, value in override.items():
        if key in merged and isinstance(merged[key], dict) and isinstance(value, dict):
            merged[key] = deep_merge(merged[key], value)
        else:
            merged[key] = value
    return merged
# 使用示例
config_files = glob.glob('configs/*.json')
merged = merge_json_configs(config_files)
with open('merged_config.json', 'w', encoding='utf-8') as f:
    json.dump(merged, f, indent=4, ensure_ascii=False)

合并INI配置文件

import configparser
from pathlib import Path
def merge_ini_configs(config_files, output_file):
    """合并INI配置文件"""
    merged_config = configparser.ConfigParser()
    for file_path in config_files:
        try:
            config = configparser.ConfigParser()
            config.read(file_path, encoding='utf-8')
            for section in config.sections():
                if not merged_config.has_section(section):
                    merged_config.add_section(section)
                for key, value in config.items(section):
                    merged_config.set(section, key, value)
        except configparser.Error as e:
            print(f"INI文件错误 {file_path}: {e}")
    with open(output_file, 'w', encoding='utf-8') as f:
        merged_config.write(f)
# 使用示例
ini_files = ['app.ini', 'database.ini', 'cache.ini']
merge_ini_configs(ini_files, 'merged_config.ini')

合并YAML配置文件

import yaml
import os
def merge_yaml_configs(config_files):
    """合并YAML配置文件"""
    merged_config = {}
    for file_path in config_files:
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                config = yaml.safe_load(f)
                if config:
                    merged_config = deep_merge(merged_config, config)
        except FileNotFoundError:
            print(f"文件不存在: {file_path}")
        except yaml.YAMLError as e:
            print(f"YAML格式错误 {file_path}: {e}")
    return merged_config
# 使用示例
yaml_files = ['config_default.yaml', 'config_custom.yaml']
merged = merge_yaml_configs(yaml_files)
with open('merged_config.yaml', 'w', encoding='utf-8') as f:
    yaml.dump(merged, f, default_flow_style=False, allow_unicode=True)

智能合并(支持优先级)

import json
from pathlib import Path
from typing import Dict, List
class ConfigMerger:
    """智能配置文件合并器"""
    def __init__(self, config_dir: str = '.'):
        self.config_dir = Path(config_dir)
    def merge_with_priority(self, base_file: str, override_files: List[str], output_file: str):
        """
        按优先级合并配置文件
        后面的文件覆盖前面的文件
        """
        all_files = [base_file] + override_files
        merged_config = {}
        for file_path in all_files:
            full_path = self.config_dir / file_path
            config = self._load_config(full_path)
            if config:
                # 记录来源
                self._add_source_info(config, str(file_path))
                merged_config = deep_merge(merged_config, config)
        # 保存合并结果
        output_path = self.config_dir / output_file
        with open(output_path, 'w', encoding='utf-8') as f:
            json.dump(merged_config, f, indent=4, ensure_ascii=False)
        return merged_config
    def _load_config(self, file_path: Path) -> Dict:
        """根据文件扩展名加载配置"""
        if not file_path.exists():
            print(f"文件不存在: {file_path}")
            return {}
        suffix = file_path.suffix.lower()
        if suffix == '.json':
            with open(file_path, 'r', encoding='utf-8') as f:
                return json.load(f)
        elif suffix == '.yaml' or suffix == '.yml':
            import yaml
            with open(file_path, 'r', encoding='utf-8') as f:
                return yaml.safe_load(f)
        elif suffix == '.ini':
            import configparser
            config = configparser.ConfigParser()
            config.read(str(file_path), encoding='utf-8')
            return {section: dict(config.items(section)) 
                    for section in config.sections()}
        else:
            print(f"不支持的格式: {suffix}")
            return {}
    def _add_source_info(self, config: Dict, source: str):
        """添加配置来源信息"""
        if isinstance(config, dict):
            config['_source'] = source
            for value in config.values():
                if isinstance(value, dict):
                    self._add_source_info(value, source)
# 使用示例
merger = ConfigMerger('./configs')
# 基础配置 + 环境配置 + 本地覆盖
merged = merger.merge_with_priority(
    base_file='default.json',
    override_files=['development.json', 'local.json'],
    output_file='merged_config.json'
)

命令行工具版本

#!/usr/bin/env python3
import argparse
import json
import glob
import os
def main():
    """命令行配置文件合并工具"""
    parser = argparse.ArgumentParser(description='合并多个配置文件')
    parser.add_argument('files', nargs='+', help='配置文件的路径')
    parser.add_argument('-o', '--output', default='merged_config.json', 
                       help='输出文件路径')
    parser.add_argument('-t', '--type', choices=['json', 'yaml', 'ini'], 
                       default='json', help='配置文件类型')
    parser.add_argument('--overwrite', action='store_true', 
                       help='覆盖已有值(默认保留第一个出现的值)')
    args = parser.parse_args()
    # 展开通配符
    config_files = []
    for pattern in args.files:
        config_files.extend(glob.glob(pattern))
    if not config_files:
        print("没有找到配置文件")
        return
    # 根据类型选择合并方法
    if args.type == 'json':
        merged = merge_json_configs(config_files)
        with open(args.output, 'w', encoding='utf-8') as f:
            json.dump(merged, f, indent=4, ensure_ascii=False)
    elif args.type == 'yaml':
        import yaml
        merged = merge_yaml_configs(config_files)
        with open(args.output, 'w', encoding='utf-8') as f:
            yaml.dump(merged, f, default_flow_style=False)
    elif args.type == 'ini':
        merge_ini_configs(config_files, args.output)
    print(f"已合并 {len(config_files)} 个配置文件到 {args.output}")
if __name__ == '__main__':
    main()

使用建议

  1. 简单场景:使用拼接方式即可
  2. 结构化数据:推荐使用JSON或YAML格式的深度合并
  3. 生产环境:建议实现完整的合并器,支持优先级、错误处理和日志
  4. 配置文件格式:优先使用JSON(标准库支持)或YAML(可读性更好)
  5. 版本控制:合并前建议备份原始配置

需要根据具体场景选择合适的合并策略!

抱歉,评论功能暂时关闭!