setup.cfg 应统一用无 BOM 的 UTF-8 编码保存,因 ConfigParser 默认按系统 locale 解码,BOM 或非 UTF-8 编码会导致 MissingSectionHeaderError 等跨平台解析错误。

setup.cfg 本身不支持声明编码格式,强行在文件开头加 encoding = utf-8 或类似语句会被 ConfigParser 忽略,甚至引发解析错误。真正起作用的是读取方(如 setuptools、pbr、自定义脚本)如何打开它——而 Python 标准库默认按系统 locale 解码,这正是跨平台出错的根源。
为什么 setup.cfg 会因编码报错
常见错误如 WARNING: Ignore distutils configs in setup.cfg due to encoding errors 或 configparser.MissingSectionHeaderError: file contains no section headers. file: 'setup.cfg', line: 1 '\ufeff[metadata]',本质是:
- 文件实际是 UTF-8 with BOM(Windows 记事本/旧版编辑器常默认保存成这样),
\ufeff被当作文本内容而非 BOM,导致第一行变成无效字符 +[metadata],ConfigParser拒绝识别 section 头 - 文件用 GBK/ISO-8859-1 等非 UTF-8 编码保存,但 Linux/macOS 上 Python 默认用 UTF-8 打开,字节流解码失败
- 不同操作系统默认 locale 不同(如 Windows 中文系统是 cp936),同一份文件在不同机器上被解释为不同字符集
正确做法:统一用无 BOM 的 UTF-8 保存文件
这不是“在 setup.cfg 里写编码”,而是确保文件字节流本身符合跨平台工具链预期:
- 用 VS Code、PyCharm、Sublime Text 等现代编辑器打开
setup.cfg,右下角查看当前编码,点击后选 Save with Encoding → UTF-8(注意勾选“without BOM”或等效选项) - 命令行验证:
file -i setup.cfg应输出charset=utf-8;xxd setup.cfg | head -n1第一行不应以ef bb bf开头(即无 BOM) - 若已有 BOM,可用 Python 快速清理:
with open('setup.cfg', 'rb') as f: content = f.read() if content.startswith(b'\xef\xbb\xbf'): content = content[3:] with open('setup.cfg', 'wb') as f: f.write(content)
读取时显式指定 encoding=None(关键兼容技巧)
如果你自己用 ConfigParser 读取 setup.cfg(比如写构建辅助脚本),不要硬写 encoding='utf-8':
- 写成
config.read('setup.cfg', encoding=None)—— 这会让ConfigParser内部调用open()时不传encoding参数,从而使用底层 C 库的 locale-aware 行为,在多数场景下反而更鲁棒 - 这是解决
MissingSectionHeaderError最直接有效的方式,尤其当文件可能含中文注释又无法完全控制保存方式时 - setuptools/pbr 等工具内部读取时也默认走这个路径,所以你无需改它们的源码,只需管好自己的文件字节流
最易被忽略的一点:即便你本地修复了 setup.cfg 编码,CI 流水线(如 GitHub Actions Ubuntu runner)仍可能因 Git 配置或编辑器提交时带入 BOM 而复现问题。建议在 .gitattributes 中加入 setup.cfg text eol=lf encoding=utf-8 并配合 pre-commit 钩子校验 BOM。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











