You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Makefile无法激活venv虚拟环境,执行提示pytest未找到

问题分析:Makefile中虚拟环境无法激活导致找不到pytest

原Makefile代码

.ONESHELL:

TEST_DIR = ./tests
DIR_NAME = $(shell date "%Y-%m-%d_%T")

.PHONY: clean test backup env

env:
    . .venv/bin/activate

test: env clean
    pytest --cache-clear --cov -p no:logging --html=report.html --self-contained-html -n 8 --maxprocesses=8 $(TEST_DIR)

backup: 
    mkdir -p ./backup_test_results
    cd ./backup_test_results
    mkdir $(DIR_NAME) && cd $(DIR_NAME)
    find . -name htmlcov -type d -exec cp -r '{}' ./ \;
    find . \( -name "error.log" -o -name "download.log" -o -name ".coverage*" -o -name "report.html" \) -type f -exec cp '{}' ./ \;
    cd ../../

clean: backup
    find . -path ./.venv -prune -o \( -name __pycache__ -o -name .pytest_cache  -o -name htmlcov \) -type d -exec rm -rf '{}' \;
    find . \( -name "error.log" -o -name "download.log" -o -name ".coverage*" -o -name "report.html" \) -type f -delete

问题描述

已启用.ONESHELL指令,目录可按预期创建,但venv虚拟环境无法激活。执行该Makefile时出现“找不到pytest”的错误,推测虚拟环境未成功激活。


核心问题

每个Makefile目标都是独立的shell进程,.ONESHELL仅作用于单个目标内的多行命令,让它们在同一个shell进程中执行,但不同目标之间的进程是完全隔离的。env目标中激活虚拟环境的操作只在它自己的shell进程里生效,进程结束后环境状态不会传递给后续的test目标,导致test目标仍然在系统全局环境中执行,自然找不到虚拟环境里的pytest。


两种修复方案

方案1:将激活命令与pytest命令放在同一目标中

利用.ONESHELL的特性,把虚拟环境激活和测试命令合并到test目标的同一shell进程中:

.ONESHELL:

TEST_DIR = ./tests
DIR_NAME = $(shell date "%Y-%m-%d_%T")

.PHONY: clean test backup

test: clean
    . .venv/bin/activate
    pytest --cache-clear --cov -p no:logging --html=report.html --self-contained-html -n 8 --maxprocesses=8 $(TEST_DIR)

backup: 
    mkdir -p ./backup_test_results
    cd ./backup_test_results
    mkdir $(DIR_NAME) && cd $(DIR_NAME)
    find . -name htmlcov -type d -exec cp -r '{}' ./ \;
    find . \( -name "error.log" -o -name "download.log" -o -name ".coverage*" -o -name "report.html" \) -type f -exec cp '{}' ./ \;
    cd ../../

clean: backup
    find . -path ./.venv -prune -o \( -name __pycache__ -o -name .pytest_cache  -o -name htmlcov \) -type d -exec rm -rf '{}' \;
    find . \( -name "error.log" -o -name "download.log" -o -name ".coverage*" -o -name "report.html" \) -type f -delete

方案2:直接调用虚拟环境内的pytest路径

跳过激活虚拟环境的步骤,直接使用虚拟环境中pytest的绝对路径执行命令,避免进程环境隔离的问题:

.ONESHELL:

TEST_DIR = ./tests
DIR_NAME = $(shell date "%Y-%m-%d_%T")

.PHONY: clean test backup

test: clean
    .venv/bin/pytest --cache-clear --cov -p no:logging --html=report.html --self-contained-html -n 8 --maxprocesses=8 $(TEST_DIR)

backup: 
    mkdir -p ./backup_test_results
    cd ./backup_test_results
    mkdir $(DIR_NAME) && cd $(DIR_NAME)
    find . -name htmlcov -type d -exec cp -r '{}' ./ \;
    find . \( -name "error.log" -o -name "download.log" -o -name ".coverage*" -o -name "report.html" \) -type f -exec cp '{}' ./ \;
    cd ../../

clean: backup
    find . -path ./.venv -prune -o \( -name __pycache__ -o -name .pytest_cache  -o -name htmlcov \) -type d -exec rm -rf '{}' \;
    find . \( -name "error.log" -o -name "download.log" -o -name ".coverage*" -o -name "report.html" \) -type f -delete

补充说明

  • 方案1贴近手动操作习惯,但依赖.ONESHELL保证同一目标的命令在同一shell执行;
  • 方案2更直接稳定,完全规避了环境传递的问题,推荐优先使用。

内容的提问来源于stack exchange,提问作者GreninjaShuriken4

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 15:46:29