pytest 不支持通过配置文件设置源文件编码,因 Python 解释器严格遵循 PEP 263 识别文件头 coding 声明,默认 UTF-8;需用 pre-commit 钩子检查 BOM、文件头声明及换行符,并在 open() 中显式指定 encoding。

pytest 本身不提供强制设置源文件编码的配置项,所谓“统一编码”必须从 Python 解释器行为和项目工程规范两层入手,而非依赖 pytest 配置文件。
为什么 pytest.ini 或 pyproject.toml 里加 encoding 没用
pytest 的配置文件(如 pytest.ini、pyproject.toml)中并不存在控制 Python 源码读取编码的 encoding 选项。Python 解释器在加载 .py 文件时,严格遵循 PEP 263:只识别文件开头的 # -*- coding: utf-8 -*- 或 # coding=utf-8 这类注释;若无,则默认为 UTF-8(自 Python 3.0 起)。pytest 不会重写或覆盖这一机制。
- 你尝试在
pytest.ini中写encoding = utf-8—— pytest 会静默忽略该字段 - 你在
pyproject.toml的[tool.pytest.ini_options]下加encoding = "utf-8"—— 同样无效,不是合法配置项 - 即使所有测试文件都含 BOM,Windows 上某些编辑器可能误判编码,但 Python 解释器仍按 PEP 263 规则处理,BOM 并非可靠依据
真正起效的强制手段:预检 + 预处理
要让整个测试项目“统一编码”,关键是阻断非 UTF-8 文件进入执行流程。不能靠 pytest 配置,而应借助 pre-commit 或 CI 流程做静态检查与自动修复。
- 用
file命令或chardet库检测单个文件编码:chardet test_example.py,但不适合批量集成 - 推荐使用
pre-commit钩子:pip install pre-commit,并在.pre-commit-config.yaml中加入:
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: check-byte-order-marker # 拒绝 BOM
- id: end-of-file-fixer # 确保换行符一致(间接影响编码感知)
- id: check-ast # 语法检查前先过编码关
- 更进一步,用
pylint或自定义脚本扫描所有.py文件头,验证是否含coding:声明且值为utf-8;缺失或错误则报错退出
Windows 下中文路径/参数导致 UnicodeEncodeError 怎么办
这不是源码编码问题,而是终端/环境变量导致的标准流编码不匹配,常见于 pytest 执行时打印含中文的测试名或异常信息时报错:
立即学习“Python免费学习笔记(深入)”;
UnicodeEncodeError: 'charmap' codec can't encode character '\u4f60' in position 0: character maps to <undefined>
- 根本原因是 Windows 控制台默认使用
cp936(GBK),而 Python 3 在非 UTF-8 终端中对sys.stdout.encoding判断失准 - 临时解决:运行前执行
chcp 65001切换控制台为 UTF-8 - 长期方案:在
pyproject.toml中启用 pytest 的--tb=short减少输出量,或用pytest --log-cli-level=WARNING避免日志刷屏 - 终极规避:CI 环境统一用 GitHub Actions / GitLab CI(Linux runner),天然 UTF-8 友好;本地开发可改用 Windows Terminal + WSL2
最常被忽略的一点:即便所有 .py 文件声明了 utf-8,若测试中读取外部文本文件(如 open("data.txt")),仍需显式指定 encoding="utf-8" —— Python 的 open() 默认编码取决于系统 locale,Windows 上很可能不是 UTF-8。


















