最可靠的方式是组合判断:优先检查 "pytest" in sys.modules,其次 fallback 到 os.environ.get("PYTEST_RUNNING") == "1",必要时用 inspect.stack() 追溯调用栈;需注意执行时机差异。
sys.argv 中是否包含 pytest 相关参数pytest 启动时通常会在 sys.argv 开头插入自身路径,后续可能带 -x、--tb=short 等标志;但仅靠参数不可靠——用户可能手动运行脚本并传入类似参数。更稳妥的做法是结合多个信号判断。
sys.argv[0] 是否以 pytest 或 py.test 结尾(注意跨平台路径分隔符)argv[0] 是 IDE 生成的路径,而非 pytest
"pytest" in sys.modules,但需注意:pytest 模块未必已完全初始化,尤其在 conftest.py 执行早期pytest 是否已在 sys.modules 中注册pytest 在启动过程中会提前将自身模块注入 sys.modules,哪怕还没执行到测试函数。这个检查比解析命令行更稳定,且开销极小。
"pytest" in sys.modules 判断即可,无需导入 pytest(否则可能触发意外初始化)pytest_configure 钩子之前执行(比如顶级 import 时),该检查可能为 False,属于正常时序问题sys.modules,此时需 fallback 到其他方式os.environ 检查 pytest 特有环境变量
pytest 本身不设置标准环境变量,但常用插件(如 pytest-xdist)会注入 PYTEST_XDIST_WORKER,而 CI 环境中常由 wrapper 脚本设 PYTEST_RUNNING=1。这不是 pytest 原生行为,但实践中很常见。
os.environ.get("PYTEST_RUNNING") == "1" 是最轻量的协作式方案PYTEST_XDIST_WORKER 单独判断,因为单进程运行时它不存在pytest.ini 的 addopts 中加 --env=PYTEST_RUNNING=1,再配合 pytest-env 插件传播inspect.stack() 追溯调用栈是否含 pytest 框架路径这是兜底方案,适用于上述方法都失效的边缘场景(如嵌入式测试、自定义 runner)。原理是看当前帧的上层是否来自 pytest 的 _pytest/ 或 py/_ 路径。
any("pytest" in frame.fil
ename or "_pytest" in frame.filename for frame in inspect.stack())
inspect.stack() 的开销做了优化,但仍比前几种方式重一个数量级frame.filename 不含明显关键词conftest.py 导入阶段、测试函数内部、fixture 初始化时,可用的上下文信号完全不同。别只依赖单一条件。