Python模块找不到:venv为何能解决该问题?
项目结构
project ├── src │ ├── module_a │ │ ├── foo.py │ │ └── __init__.py │ ├── runner.py │ ├── constants.py │ └── __init__.py
相关代码
constants.py
SOME_CONST = 5
foo.py
from src.constants import SOME_CONST class Foo: def some_func(self): # 省略具体实现 pass
runner.py
from src.module_a.foo import Foo def main(): Foo.some_func() if __name__ == "__main__": main()
执行情况:在src目录下运行python runner.py时,foo.py中的from src.constants import SOME_CONST抛出ModuleNotFoundError,提示找不到src模块;创建虚拟环境后问题解决。
疑问解答
1. 为何创建虚拟环境前,Python解释器不识别src文件夹为模块?
Python查找模块依赖sys.path这个路径列表,当你在src目录下直接运行python runner.py时,Python只会把**当前工作目录(即src目录)**加入sys.path。而src本身并不在sys.path里,所以当foo.py尝试导入src.constants时,Python找不到名为src的模块。
2. 为何创建虚拟环境能解决该问题?
激活虚拟环境后,如果你用pip install -e .(可编辑安装)把项目安装到虚拟环境,虚拟环境的site-packages目录会生成一个指向project目录的.pth文件,这个文件会让Python自动把project目录加入sys.path。此时src作为project下的子目录,就被识别为可导入的模块了——因为project在sys.path里,Python能找到src这个包。
3. 如何配置项目使其无需虚拟环境即可运行?
有三种实用方式:
方式一:临时设置PYTHONPATH环境变量
运行脚本时,把project目录(src的父目录)添加到PYTHONPATH:
# Linux/macOS cd src PYTHONPATH=.. python runner.py # Windows(命令提示符) cd src set PYTHONPATH=.. && python runner.py # Windows(PowerShell) cd src $env:PYTHONPATH=".." ; python runner.py
方式二:在脚本中手动添加路径
在runner.py的最顶部加入以下代码,让脚本自己把project目录加入sys.path:
import sys from pathlib import Path # 获取project目录的绝对路径 project_dir = Path(__file__).parent.parent sys.path.append(str(project_dir)) # 原来的导入和业务代码 from src.module_a.foo import Foo def main(): Foo().some_func() # 注:原代码中some_func是实例方法,需要先实例化Foo类 if __name__ == "__main__": main()
方式三:从项目根目录以模块模式运行
切换到project目录,用Python的模块运行命令执行脚本:
python -m src.runner
这种模式会自动把当前工作目录(project)加入sys.path,src作为模块能被正确识别,runner作为src的子模块运行。
内容的提问来源于stack exchange,提问作者Eyal Golan

