INI 配置文件语法速查表 - INI 配置格式常用命令大全
INI 语法足够简单,但解析器各不相同:注释符号、引号处理、是否支持嵌套与变量引用都随实现而异。这份速查按 8 组整理基础语法、数据类型,以及 Windows、php.ini、Git config、Python configparser 四类真实场景的写法;同时单列一组"解析注意事项"说明跨解析器的差异陷阱。读完后你能快速判断某段 INI 在目标解析器下是否安全,并规避 BOM、重复键、注释符号等常见坑。
典型使用场景
面向需要读取或维护老式配置文件的开发者:Windows 应用配置、Git 的 .gitconfig、PHP 的 php.ini、以及用 Python configparser 消费的自定义配置。INI 的语法极简(节 + 键值对),但正因为各家解析器实现不同,跨工具时最容易出问题——注释符号分号和井号、引号是否保留、重复键怎么处理、Windows 路径的反斜杠转义、UTF-8 BOM 导致首个节解析失败。本表把 PHP 与 Git 两个真实配置片段连同 Windows 特例一起列出,并给出 Python 侧 configparser 的读写与按类型读取接口,是排查「明明配了却不生效」的第一站。
基础语法 7
; 这是注释# 这也是注释[section]key = valuekey = "quoted value"key =; key = commented out数据类型 7
string = hellointeger = 42float = 3.14boolean = truearray = value1,value2,value3hex = 0xFFpercent = 50%常见应用 5
[database]
host = localhost
port = 3306[server]
listen = 8080
max_connections = 100[logging]
level = info
file = /var/log/app.log[user]
name = Alice
email = alice@example.com[cache]
driver = redis
ttl = 3600PHP php.ini 示例 9
[PHP]
memory_limit = 256Mupload_max_filesize = 20Mpost_max_size = 25Mmax_execution_time = 30display_errors = Onerror_reporting = E_ALLdate.timezone = Asia/Shanghaisession.save_path = /tmpsession.gc_maxlifetime = 1440Git 配置示例 7
[user]
name = Your Name
email = you@example.com[core]
editor = vim
autocrlf = input[alias]
co = checkout
br = branch
lg = log --oneline --graph[remote "origin"]
url = https://github.com/user/repo.git[diff]
tool = vimdiff[merge]
tool = vimdiff
conflictstyle = diff3[pull]
rebase = trueWindows INI 示例 5
path = C:\\Program Files\\App[Environment]
PATH = %PATH%;C:\\bintemp = %TEMP%\\appapp_dir = ${APPDIR}key = value ; trailing commentPython configparser 6
config.read("config.ini")config.write(open("config.ini", "w"))config["section"]["key"]config["section"]["key"] = "value"config["DEFAULT"]["key"]config.getint("section", "port")解析注意事项 6
; vs #key="value" vs key = value[[nested]]BOM: \xEF\xBB\xBFkey = ; not a commentduplicate keys参数矩阵
| 参数 | 作用 | 示例 |
|---|---|---|
; 注释 | 分号注释,最通用 | ; 这是注释 |
# 注释 | 井号注释,部分解析器支持 | # 这也是注释 |
[section] | 节(section)定义,配置分组的唯一手段 | [database] |
key = value | 键值对,等号两边空格会被自动去除 | host = localhost |
key = "quoted value" | 带引号的值,含空格或特殊字符时使用 | name = "Alice B" |
key = | 空值 | path = |
boolean = true | 布尔值(true/false/yes/no/on/off) | display_errors = On |
array = a,b,c | 逗号分隔的数组(解析器相关) | tags = a,b,c |
hex = 0xFF | 十六进制值(部分解析器支持) | mask = 0xFF |
percent = 50% | 百分比值 | percent = 50% |
[core] editor / autocrlf | Git 核心配置:默认编辑器与换行转换 | [core]
editor = vim |
[alias] co / br / lg | Git 命令别名 | lg = log --oneline --graph |
[merge] conflictstyle | 合并冲突显示风格(diff3) | [merge]
tool = vimdiff
conflictstyle = diff3 |
[PHP] memory_limit | PHP 内存限制 | memory_limit = 256M |
post_max_size / upload_max_filesize | POST 数据与上传文件大小上限 | post_max_size = 25M |
session.gc_maxlifetime | Session 最大生存时间(秒) | session.gc_maxlifetime = 1440 |
date.timezone | 时区设置 | date.timezone = Asia/Shanghai |
config.read("config.ini") | Python 读取 INI 文件 | config.read("config.ini") |
config.getint("section", "port") | 按类型读取(getint/getfloat/getboolean) | config.getint("server", "port") |
config["DEFAULT"]["key"] | 所有节继承的默认值 | config["DEFAULT"]["encoding"] |
易错点与避坑指南
现象配置文件的第一个节读不到,报 KeyError 或 section 不存在
原因文件开头有 UTF-8 BOM(\xEF\xBB\xBF),BOM 被当成了节名的一部分。
处置把文件另存为 UTF-8 无 BOM,或在读取前先剥离 BOM 字节。
现象值里出现多余的引号,比如程序读到的是 "hello" 而不是 hello
原因不同解析器对引号的处理不一致:有的去掉外层引号,有的原样保留。
处置值中不含空格和特殊字符时干脆不加引号;必须加时先确认目标解析器的实际行为。
现象配置项怎么改都不生效,程序像是完全没读这个文件
原因注释符号用错了,该解析器只认分号不认井号(或相反),整行被当成注释。
处置统一改用分号 ; 作为注释符,这是跨解析器最通用的写法。
现象Windows 路径写进去后目录拼错,多出一层反斜杠或找不到目录
原因INI 中的反斜杠是转义符,单个 \ 会被当成转义起始。
处置用双反斜杠 C:\\Program Files\\App 写出,或直接改用正斜杠。
现象想按层级组织配置,结果解析器直接报错
原因标准 INI 不支持嵌套节,[[nested]] 只是部分工具的非标准扩展。
处置改用 YAML 或 TOML 这类真正支持嵌套的格式;必须用 INI 时用下划线模拟层级,如 db_host = ...。
现象同一个键写了两次,最后读到哪一个不确定
原因重复键的行为由解析器决定:有的后者覆盖前者,有的直接报错。
处置保证每个节内键唯一;写配置的程序应先读后写而不是整段覆盖拼接。
现象读取 %TEMP% 这类写法时拿到的是字面量而不是展开后的路径
原因变量插值是 Windows 系统配置文件的特性,多数程序自己的 INI 解析器并不支持。
处置把路径由程序在运行时拼接传入配置文件,或改用 Python 的 ExtendedInterpolation 并改用 $(...) 语法。
排障路径
1检查文件开头是否有 BOM
head -c 3 config.ini | xxd若输出为 efbb bf,说明存在 UTF-8 BOM,需要重新保存为无 BOM 编码。
2打印解析器实际读到的全部节与键
python -c "import configparser; c=configparser.ConfigParser(); c.read('config.ini'); print([s for s in c.sections()]); print(dict(c['DEFAULT']))"sections() 为空说明文件根本没被读进来,DEFAULT 里的内容则是所有节的公共默认值。
3按类型读取单个值以确认解析结果
python -c "import configparser; c=configparser.ConfigParser(); c.read('config.ini'); print(c.getint('server', 'port'))"能打印出整数说明解析成功;若报 ValueError,说明值不是合法数字或带了残留引号。
4查看原始行以核对注释符与引号
grep -n '^\s*['\";#[]' config.ini输出可逐行核对节定义、注释行和取值写法,异常写法一眼可见。
5确认 Git 实际生效的配置
git config --list --show-origin输出会标注每个配置项来自哪个文件,用来定位全局与仓库级配置相互覆盖的问题。
命令示例
按节与类型读取,而不是手工 split
import configparser
config = configparser.ConfigParser()
config.read("config.ini")
config.getint("database", "port")config.read 返回实际读到的文件名列表,文件不存在时返回空列表而不抛异常,所以后面必须显式判断。取值走 getint / getfloat / getboolean,解析器会替你转换类型并做校验,比自己 string.split("=") 稳得多。
输出
3306
DEFAULT 节作为全局默认值被各节继承
[DEFAULT]
mode = dev
[server]
host = 127.0.0.1DEFAULT 不是普通节,不能被 has_section 命中,也不会出现在 items() 里,但它对所有节都可见。适合把环境无关的共同默认值集中放一处,各节只写差异。
输出
config.get('server', 'mode') -> 'dev'改值后整份写回,注释会全部丢失
config["cache"]["ttl"] = "7200"
with open("config.ini", "w") as f:
config.write(f)ConfigParser 只保存「解析后的数据」,不保留原始文本,行尾注释与键的书写格式在写回时全部消失。如果文件里有大量给人看的注释,需要改用能保注释的方案,或只做「读—改—局部替换」而不是整份重写。
写出来看着对,解析器读出来却是空
key = ; not a comment行尾注释只有部分解析器支持,多数实现会把分号连同后面的内容一起当成值。值里需要分号时必须加引号,或者干脆避免在值中使用分号。
输出
config.get('section', 'key') -> '; not a comment'Windows 路径必须转义反斜杠
path = C:\\Program Files\\Appini 的转义符就是反斜杠,不写双反斜杠时 \P 与 \A 会被当成转义序列,路径被吃掉一段且不会有任何报错。跨平台配置里建议统一用正斜杠。
常见坑与注意事项
- 写错节名或键名不会报错,只是取不到值:多数取值函数在键缺失时抛 KeyError/NoSectionError,而 defaults 命中的场景又会静默返回 DEFAULT 里的值,排查时极易误判。
- config.read() 对不存在的文件返回空列表而不抛异常,漏写文件时后面全部拿到 DEFAULT 值,配置「看起来生效了」实际没加载。
- 同名键重复出现时行为由解析器决定:后写的覆盖先写的,或直接报错。同一节里重复写同名键是很隐蔽的 bug 来源。
- getint 遇到非数字值会抛 ValueError,配置里误填 3306ms 这类带单位的值就会在读取时炸掉。
- 键名与节名默认按全小写匹配(除非显式设置 optionxform),写成 [Server] 而读取时用 config.get("Server", ...) 在某些实现上会取不到。
- 整份写回会丢掉所有注释和原始格式,配置文件若是人工维护的,不要用解析器整份覆写。
提示
- INI 语法简单,但不支持嵌套结构,复杂配置建议用 YAML 或 TOML。
- 不同解析器对注释符号支持不同,分号(;)最通用。
- 键值对的等号两边可以有空格,解析器会自动去除。
- Windows 路径中的反斜杠需注意转义,建议用正斜杠或双反斜杠。
- Python configparser 不支持默认值的变量插值,需用 ExtendedInterpolation。
- INI 文件编码建议统一使用 UTF-8 无 BOM,避免解析首节失败。
常见问题
为什么解析器读不到 INI 文件里的第一个节?
最常见的原因是文件带了 UTF-8 BOM,也就是开头三字节 \xEF\xBB\xBF,解析器会把它当成第一个节名的一部分,于是首节匹配失败。解决办法是存成「UTF-8 无 BOM」。其次是注释符号:分号 ; 最通用,井号 # 只有部分解析器支持,写配置时优先用分号。编码统一后再排查重复键——同一个节里出现两次同名键时,行为不明确,有的解析器后者覆盖前者,有的直接报错。
INI 不支持嵌套节,配置需要多层结构怎么办?
标准 INI 只有「节 + 键值」两层,写作 [[nested]] 属于非标准扩展,换个工具就可能失效。需要在节里表达列表或结构时,可以把值写成逗号分隔的数组形式 array = value1,value2,value3。如果配置确实需要深层嵌套、列表里再套字典,直接换 YAML 或 TOML,它们的嵌套能力是 INI 给不了的。简单扁平配置继续留在 INI,迁移成本才最低。
Windows 路径里的反斜杠为什么老出问题?
反斜杠在 INI 里同时是路径分隔符和转义符,path = C:\\Program Files\\App 这种写法正是为了让解析器把 \ 读成单个反斜杠;只写一个 C:\Program Files 时第二个反斜杠可能被当作转义序列的开头。最省心的办法是直接用正斜杠,多数解析器都接受,Windows 本身也认。值里带空格时加双引号:app_dir = "C:\\Program Files\\App",引号包住整段路径。
用 Python configparser 读取时,值类型和默认值该怎么处理?
读取用 config.read("config.ini"),取值走 config["section"]["key"],写入用 config["section"]["key"] = "value" 后 config.write(open("config.ini", "w")) 落盘。类型转换有专用方法:config.getint("section", "port") 把 3306 读成整数,getfloat 与 getboolean 同理,避免手工转。默认值写在 config["DEFAULT"]["key"],所有节都能继承。注意默认的 configparser 不做变量插值,要用 %VAR% 得显式启用 ExtendedInterpolation。
什么场景下 INI 才是合适的选择?
扁平、单层、以键值为主的配置最适合 INI:数据库连接([database] host = localhost port = 3306)、服务器参数、日志级别、缓存驱动与 TTL、用户信息。本表收录的 php.ini 片段也是这个形态——memory_limit = 256M、date.timezone = Asia/Shanghai 这类一行一个开关的设置。判断标准很简单:只要你想表达「列表里再放字典」或深层嵌套,就说明该换 YAML 或 TOML 了。
由 巧匠 维护
公开更新于 2026年7月21日,内容持续校对官方文档。