同样的一个 python
脚本,在 pycharm
里直接运行没问题,到了 vscode
运行却报错 ModuleNotFoundError: No module named 'xxx'
?
场景
示例项目结构如下:
test
├── app
│ └── config.py
├── tests
│ ├── check_path.py
│ └── test_config.py
└── main.py
其中 tests/test_config.py
:
from app import config
def test_config():
if config.ENV == "prod":
assert config.IS_PROD == True
if __name__ == "__main__":
test_config()
直接运行 python .\tests\test_config.py
,会得到报错 ModuleNotFoundError: No module named 'app'
:
python .\tests\test_config.py
Traceback (most recent call last):
File ".\tests\test_config.py", line 1, in <module>
from app import config
ModuleNotFoundError: No module named 'app'
这是由于导入包路径问题导致的,子目录下的脚本在终端直接运行时,导入包路径默认是脚本所在目录,而不包含上级目录,如果在脚本中导入了其他目录下的包(测试时很常见),则会报错。
大部分时候,服务入口脚本大多是在项目根目录运行,那这个时候导入包的目录就是项目根目录,所有的子目录包都可以正常使用。
在 pycharm
里执行没有报错是因为 pycharm
会自动将工作目录加入导入包路径中的,要查看导入包路径,可以这样:
在 tests/check_path.py
:
import sys
if __name__ == "__main__":
for path in sys.path:
print(path)
运行 python .\tests\check_path.py
会输出:
D:\projects-python\test\tests
C:\Users\kb\AppData\Local\Programs\Python\Python38\python38.zip
C:\Users\kb\AppData\Local\Programs\Python\Python38\DLLs
C:\Users\kb\AppData\Local\Programs\Python\Python38\lib
C:\Users\kb\AppData\Local\Programs\Python\Python38
D:\projects-python\test\.venv
D:\projects-python\test\.venv\lib\site-packages
可以看到导入包路径中只包含当前目录 D:\projects-python\test\tests
,而不包含项目根目录 D:\projects-python\test
,自然就无法导入根目录下其他目录下的包了。
解决
在 vscode
配置文件 settings
中添加 PYTHONPATH
配置:
"terminal.integrated.env.windows": {"PYTHONPATH":"${workspaceFolder};${env:PYTHONPATH}"},
其实就是将当前工作目录添加到环境变量 PYTHONPATH
(默认模块搜索路径)中,这个环境变量的值默认就是 sys.path
。
重启 vscode
后,再次运行 python .\tests\check_path.py
输出:
D:\projects-python\test\tests
D:\projects-python\test
C:\Users\kb\AppData\Local\Programs\Python\Python38\python38.zip
C:\Users\kb\AppData\Local\Programs\Python\Python38\DLLs
C:\Users\kb\AppData\Local\Programs\Python\Python38\lib
C:\Users\kb\AppData\Local\Programs\Python\Python38
D:\projects-python\test\.venv
D:\projects-python\test\.venv\lib\site-packages
可以看到,这时候就包含了根目录,再运行 python .\tests\test_config.py
脚本就不会报错了。