pytest-env插件需通过pytest.ini或setup.cfg配置,不支持pyproject.toml;仅在pytest启动时注入环境变量,不覆盖手动修改的os.environ,也不自动传递给subprocess子进程。

直接用 pytest-env 插件注入环境变量是可行的,但必须注意它只在 pytest 启动时读取配置,**不会覆盖测试中手动修改的 os.environ**,且对 subprocess 启动的子进程默认无效。
如何正确安装和启用 pytest-env
这个插件本身不自带命令行开关,靠识别配置文件触发。它只认两种格式:INI 风格的 setup.cfg 或 pytest.ini,**不支持 pyproject.toml**(哪怕你用的是较新 pytest 版本)。
- 在项目根目录新建
pytest.ini,内容必须包含[tool:pytest]段落 - 添加
env配置项,每行一个KEY=VALUE形式 - 确保插件已安装:
pip install pytest-env
示例 pytest.ini:
[tool:pytest]
env =
DATABASE_URL=sqlite:///test.db
LOG_LEVEL=DEBUG
FEATURE_FLAG=true
为什么测试里 print(os.environ.get('DATABASE_URL')) 仍是 None?
常见原因是 pytest 还没加载插件——比如你用了 python -m pytest 但当前工作目录不是配置文件所在目录,或者配置文件名写错(如误写成 pyproject.ini)。pytest-env 不会报错提示配置缺失,而是静默跳过。
- 运行
pytest --help,如果输出里出现env相关描述,说明插件已加载 - 加
-v参数跑一个测试,在输出开头找类似environment variables: DATABASE_URL, LOG_LEVEL的日志行 - 确认
pytest.ini在pytest命令执行时的当前目录下,或用--config-file显式指定路径
如何让子进程也继承这些环境变量?
pytest-env 设置的变量仅影响当前 Python 进程的 os.environ,对 subprocess.run() 等启动的子进程无效——除非你显式传递 env=os.environ。
- 错误写法:
subprocess.run(['echo', '$DATABASE_URL'])→ 子进程看不到 - 正确写法:
subprocess.run(['echo', os.environ['DATABASE_URL']], env=os.environ) - 更稳妥的做法:在测试 setup 阶段用
os.environ.copy()构造干净副本,避免污染全局环境
与 pytest 的 --envfile 参数冲突吗?
如果你同时用了 pytest-dotenv 或其他读取 .env 文件的插件,它们和 pytest-env 互不感知。**pytest-env 的配置优先级高于 .env 文件**,但两者叠加时,后加载的插件会覆盖前者设置的同名变量。
- 推荐只选一种机制:要么全用
pytest-env的配置文件,要么全用.env+pytest-dotenv - 避免混用;若必须混用,用
pytest --setup-show观察实际生效的环境变量值 -
pytest-env不支持变量插值(如HOME_DIR=${HOME}/test),这点不如dotenv
真正容易被忽略的是:插件注入发生在 pytest 的 collection 阶段之前,所以任何在 conftest.py 的 pytest_configure 钩子中依赖这些变量的逻辑,必须确保钩子执行时机晚于插件初始化——而 pytest-env 默认满足这点,但自定义插件可能破坏顺序。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











