一、前言

在 Python 开发中,很多人会纠结 YAML、JSON、TOML、py 配置文件该怎么选。但如果你只是写中小型脚本、后台工具、自动化程序、轻量接口服务,INI 文件完全可以包揽全部配置需求,无需安装任何第三方库,Python 标准库自带 configparser,开箱即用、上手零门槛,运维人员不用懂代码就能修改参数。

INI 文件结构清晰、分段分组、支持注释、读写简单,没有复杂缩进、特殊语法坑,本文完整讲解纯 INI 配置实战,覆盖读取、写入、类型转换、多配置文件分离、配置持久化保存等全套代码,全程不引入任何第三方依赖。

二、INI 文件基础语法说明

INI 文件核心由「分段」「键值对」「注释」三部分组成:

  1. [section]:分段区域,用来分类配置,比如数据库、日志、接口、服务;
  2. key = value:配置项,等号两侧空格无强制要求;
  3. # 开头为注释,用于备注参数作用;
  4. 原生所有读取值默认字符串,数字、布尔、列表需要手动转换。

示例 config.ini

# 服务基础配置
[server]
debug = True
port = 8080
timeout = 30
service_name = 自动化采集工具

# 数据库连接配置
[mysql]
host = 127.0.0.1
user = root
password = root123456
db_name = test_db
pool_size = 10

# 文件输出配置
[output]
save_path = ./data
file_prefix = task_data

三、基础读取 INI 配置完整代码

Python 内置 configparser 模块,无需 pip 安装,直接导入使用:

import configparser

# 初始化解析器
cfg = configparser.ConfigParser()
# 读取ini文件,指定编码防止中文乱码
cfg.read("config.ini", encoding="utf-8")

# 1. 读取字符串类型配置
service_name = cfg.get("server", "service_name")
save_path = cfg.get("output", "save_path")
print("服务名称:", service_name)
print("文件保存路径:", save_path)

# 2. 读取数字(int/float)
port = cfg.getint("server", "port")
timeout = cfg.getint("server", "timeout")
pool_size = cfg.getint("mysql", "pool_size")
print("服务端口:", port, type(port))

# 3. 读取布尔值
debug = cfg.getboolean("server", "debug")
print("调试模式:", debug, type(debug))

# 4. 获取所有分段名称
sections = cfg.sections()
print("所有配置分组:", sections)

# 5. 获取某一分组下全部键值对
mysql_config = dict(cfg.items("mysql"))
print("数据库完整配置:", mysql_config)

读取结果说明

  • get():统一返回字符串,适合路径、账号、文本;
  • getint():自动转整型,端口、超时、连接池数量专用;
  • getfloat():浮点数值,如超时秒数、比例系数;
  • getboolean():自动识别 true/false/1/0/yes/no 转为布尔值。

四、修改、新增配置并写入保存到 INI

业务运行中需要动态更新配置、新增参数、生成新配置文件,configparser 支持直接修改内存配置后落地写入文件:

import configparser

cfg = configparser.ConfigParser()
cfg.read("config.ini", encoding="utf-8")

# 1. 修改已有配置项
cfg.set("server", "port", "8090")
cfg.set("server", "debug", "False")

# 2. 新增配置分组与参数
if not cfg.has_section("redis"):
    cfg.add_section("redis")
cfg.set("redis", "host", "127.0.0.1")
cfg.set("redis", "port", "6379")
cfg.set("redis", "password", "")

# 3. 删除配置项/分组
# cfg.remove_option("server", "timeout")
# cfg.remove_section("redis")

# 4. 写入回文件
with open("config.ini", "w", encoding="utf-8") as f:
    cfg.write(f)
print("配置修改完成,已保存至 config.ini")

五、INI 实现列表/数组配置(INI原生不支持列表,通用方案)

INI 标准没有数组语法,工程通用解决方案:用英文逗号分隔字符串,读取后分割转列表,适配白名单、多文件路径、多数据源场景。

1. ini 配置增加列表参数

[filter]
white_list = admin,test,robot,guest
target_suffix = txt,json,csv

2. 读取并转为列表

import configparser

cfg = configparser.ConfigParser()
cfg.read("config.ini", encoding="utf-8")

# 读取逗号分隔字符串并分割
white_list_str = cfg.get("filter", "white_list")
white_list = [item.strip() for item in white_list_str.split(",")]

suffix_str = cfg.get("filter", "target_suffix")
suffix_list = [s.strip() for s in suffix_str.split(",")]

print("白名单列表:", white_list)
print("文件后缀列表:", suffix_list)

六、多环境配置分离(仅用INI实现开发/生产环境)

很多项目需要区分开发、测试、生产环境,不用引入多套配置文件,单 INI 文件多分段实现:

[dev_server]
debug = True
port = 8080
mysql_host = 127.0.0.1

[prod_server]
debug = False
port = 80
mysql_host = 10.0.0.10

读取时指定环境变量切换分组:

import configparser
import os

# 可通过环境变量切换环境,默认开发环境
env = os.getenv("RUN_ENV", "dev")
cfg = configparser.ConfigParser()
cfg.read("config.ini", encoding="utf-8")

# 拼接环境分组前缀
section = f"{env}_server"
debug = cfg.getboolean(section, "debug")
port = cfg.getint(section, "port")
mysql_host = cfg.get(section, "mysql_host")

print(f"当前环境:{env}")
print(f"调试开关:{debug},端口:{port}")

七、封装全局配置工具类(项目实战标准写法)

把 INI 读写逻辑封装成工具类,项目全局调用,统一管理配置,避免重复写读取代码:

import configparser
import os

class IniConfig:
    def __init__(self, file_path="config.ini"):
        self.file_path = file_path
        self.cfg = configparser.ConfigParser()
        # 文件不存在则自动创建空ini
        if os.path.exists(self.file_path):
            self.cfg.read(self.file_path, encoding="utf-8")
        else:
            self.save()

    def get_str(self, section, key, default=""):
        if self.cfg.has_option(section, key):
            return self.cfg.get(section, key)
        return default

    def get_int(self, section, key, default=0):
        val = self.get_str(section, key)
        try:
            return int(val)
        except:
            return default

    def get_bool(self, section, key, default=False):
        if self.cfg.has_option(section, key):
            return self.cfg.getboolean(section, key)
        return default

    def get_list(self, section, key, default=None):
        if default is None:
            default = []
        val = self.get_str(section, key)
        if not val:
            return default
        return [i.strip() for i in val.split(",")]

    def set(self, section, key, value):
        if not self.cfg.has_section(section):
            self.cfg.add_section(section)
        self.cfg.set(section, key, str(value))
        self.save()

    def save(self):
        with open(self.file_path, "w", encoding="utf-8") as f:
            self.cfg.write(f)

# 全局单例配置
config = IniConfig()

# 使用示例
if __name__ == "__main__":
    # 读取
    port = config.get_int("server", "port", 8080)
    white_list = config.get_list("filter", "white_list")
    print("端口:", port, "白名单:", white_list)

    # 修改写入
    config.set("server", "timeout", 60)

八、只使用 INI 做配置的优势

  1. 零第三方依赖
    Python 标准库内置 configparser,不需要安装 PyYAML、tomli、json 额外工具,打包、部署、轻量化脚本无额外依赖冲突。

  2. 上手门槛极低,运维友好
    格式简单,无缩进、括号、逗号语法坑,非开发人员也能快速修改配置,注释清晰直观。

  3. 天然分组隔离
    [section] 分段天然区分数据库、日志、接口、文件配置,逻辑分层一目了然。

  4. 读写稳定,兼容所有系统
    Windows、Linux、Mac 全部完美支持,不存在 JSON 不能写注释、YAML 缩进报错的问题。

  5. 支持动态持久化
    程序运行时可新增、修改、删除配置并保存到本地,适合工具类程序动态保存参数。

九、INI 文件局限性与适配方案

INI 不是万能格式,有原生短板,全部可以通过简单代码弥补,无需更换配置文件:

  1. 不支持多层嵌套
    解决方案:分层命名 key,如 mysql_write_hostmysql_read_port,或拆分多 section;
  2. 无原生数组
    解决方案:逗号分割字符串读取转列表,上文已提供通用封装;
  3. 所有值默认字符串
    解决方案:封装 getint/getbool/getlist 工具方法统一转换;
  4. 复杂结构化数据存储麻烦
    解决方案:复杂字典数据单独用 json 临时存储,业务配置仍统一使用 INI。

十、适用场景总结(只推荐 INI 的场景)

  1. 自动化脚本、爬虫工具、本地小工具;
  2. 轻量 Flask/FastAPI 小型后台服务;
  3. 运维辅助程序、定时任务程序;
  4. 不想管理第三方依赖、追求极简部署的项目;
  5. 需要运维人员频繁手动修改配置的线上工具。

十一、结尾

很多开发者盲目跟风使用 YAML、TOML 做配置,忽略了 INI 轻量化、零依赖的优势。对于绝大多数中小型 Python 程序,仅靠 INI 文件就能完整承载所有业务配置,搭配简单封装类即可补齐列表、类型转换、动态修改等短板,大幅降低项目依赖与维护成本。

更多推荐