conda激活虚拟环境后系统site-packages路径优先级更高的原因及构建位置
问题描述
导入错误详情
在Miniconda3虚拟环境中导入PIL.Image时出现DLL加载失败错误,报错栈如下:
Traceback (most recent call last): File "C:\Users\capnf\miniconda3\envs\pybert-tst\lib\site-packages\enable\qt4\base_window.py", line 255, in paintEvent self.handler.paintEvent(event) File "C:\Users\capnf\miniconda3\envs\pybert-tst\lib\site-packages\enable\qt4\base_window.py", line 90, in paintEvent self._enable_window._paint(event) File "C:\Users\capnf\miniconda3\envs\pybert-tst\lib\site-packages\enable\abstract_window.py", line 536, in _paint self.component.draw(gc, view_bounds=(0, 0, size[0], size[1])) File "C:\Users\capnf\miniconda3\envs\pybert-tst\lib\site-packages\enable\component.py", line 410, in draw self._draw(gc, view_bounds, mode) File "C:\Users\capnf\miniconda3\envs\pybert-tst\lib\site-packages\enable\component.py", line 791, in _draw self._dispatch_draw(layer, gc, view_bounds, mode) File "C:\Users\capnf\miniconda3\envs\pybert-tst\lib\site-packages\enable\container.py", line 270, in _dispatch_draw component._dispatch_draw(layer, gc, new_bounds, mode) File "C:\Users\capnf\miniconda3\envs\pybert-tst\lib\site-packages\enable\container.py", line 270, in _dispatch_draw component._dispatch_draw(layer, gc, new_bounds, mode) File "C:\Users\capnf\miniconda3\envs\pybert-tst\lib\site-packages\enable\component.py", line 809, in _dispatch_draw handler(gc, view_bounds, mode) File "C:\Users\capnf\miniconda3\envs\pybert-tst\lib\site-packages\chaco\base_2d_plot.py", line 221, in _draw_image self._render(gc) File "C:\Users\capnf\miniconda3\envs\pybert-tst\lib\site-packages\chaco\plots\cmap_image_plot.py", line 101, in _render ImagePlot._render(self, gc) File "C:\Users\capnf\miniconda3\envs\pybert-tst\lib\site-packages\chaco\plots\image_plot.py", line 165, in _render gc.draw_image(self._cached_image, self._cached_dest_rect) File "C:\Users\capnf\miniconda3\envs\pybert-tst\lib\site-packages\kiva\agg\agg.py", line 1216, in draw_image from PIL import Image File "C:\Users\capnf\AppData\Roaming\Python\Python39\site-packages\shiboken2\files.dir\shibokensupport\__feature__.py", line 142, in _import return original_import(name, *args, **kwargs) File "C:\Users\capnf\AppData\Roaming\Python\Python39\site-packages\shiboken2\files.dir\shibokensupport\__feature__.py", line 142, in _import return original_import(name, *args, **kwargs) File "C:\Users\capnf\miniconda3\envs\pybert-tst\lib\site-packages\PIL\Image.py", line 100, in <module> from . import _imaging as core File "C:\Users\capnf\AppData\Roaming\Python\Python39\site-packages\shiboken2\files.dir\shibokensupport\__feature__.py", line 142, in _import return original_import(name, *args, **kwargs) File "C:\Users\capnf\AppData\Roaming\Python\Python39\site-packages\shiboken2\files.dir\shibokensupport\__feature__.py", line 142, in _import return original_import(name, *args, **kwargs) ImportError: DLL load failed while importing _imaging: The specified module could not be found.
路径异常排查
激活虚拟环境后,sys.path显示系统用户级site-packages路径优先级高于虚拟环境自身的site-packages:
(base) capnf@DESKTOP-G84ND7C MINGW64 ~ $ conda activate pybert-tst (pybert-tst) capnf@DESKTOP-G84ND7C MINGW64 ~ $ python -c "import sys; print(sys.path)" [ '' , 'C:\\Users\\capnf\\miniconda3\\envs\\pybert-tst\\python39.zip' , 'C:\\Users\\capnf\\miniconda3\\envs\\pybert-tst\\DLLs' , 'C:\\Users\\capnf\\miniconda3\\envs\\pybert-tst\\lib' , 'C:\\Users\\capnf\\miniconda3\\envs\\pybert-tst' , 'C:\\Users\\capnf\\AppData\\Roaming\\Python\\Python39\\site-packages' , 'C:\\Users\\capnf\\miniconda3\\envs\\pybert-tst\\lib\\site-packages' ]
后续处理结果
删除AppData/Roaming/Python/文件夹后,重新激活虚拟环境,异常路径不再出现:
(base) capnf@DESKTOP-G84ND7C MINGW64 ~ $ conda activate pybert-tst (pybert-tst) capnf@DESKTOP-G84ND7C MINGW64 ~ $ python -c "import sys; print(sys.path)" [ '' , 'C:\\Users\\capnf\\miniconda3\\envs\\pybert-tst\\python39.zip' , 'C:\\Users\\capnf\\miniconda3\\envs\\pybert-tst\\DLLs' , 'C:\\Users\\capnf\\miniconda3\\envs\\pybert-tst\\lib' , 'C:\\Users\\capnf\\miniconda3\\envs\\pybert-tst' , 'C:\\Users\\capnf\\miniconda3\\envs\\pybert-tst\\lib\\site-packages' ]
疑问
- 为何用户级site-packages路径会排在虚拟环境site-packages之前?
- conda激活虚拟环境时的Python搜索路径是否通过动态编程构建?如果是,构建逻辑在哪里执行?
解答
1. 用户级site-packages路径优先级异常的原因
C:\Users\capnf\AppData\Roaming\Python\Python39\site-packages是Python的USER_SITE目录,属于用户级包安装路径,通常由pip install --user命令生成。出现优先级高于虚拟环境site-packages的情况,主要有两个原因:
- 之前在全局Python环境下执行过
pip install --user,该操作会在USER_SITE目录生成配置文件(如.pth文件),这些配置会被Python加载,即使在conda虚拟环境中也会被优先读取。 - 环境变量
PYTHONUSERBASE被全局设置,强制Python加载该目录,而conda激活虚拟环境时未覆盖这个变量。
正常情况下,conda虚拟环境会通过修改Python的site模块配置,让虚拟环境的site-packages优先级更高,但上述两种情况会干扰这个逻辑。
2. conda虚拟环境sys.path的构建逻辑
conda激活虚拟环境时,确实是动态构建Python搜索路径的,核心执行点包括:
- conda激活脚本:激活虚拟环境时,conda会修改系统
PATH变量,将虚拟环境的Scripts(Windows)/bin(Linux/macOS)目录放在最前面,确保调用的是虚拟环境内的Python解释器。 - Python内置的site模块:虚拟环境内的Python解释器会通过
Lib/site.py文件构建sys.path。conda会修改虚拟环境的site.py,默认禁用全局site-packages,但USER_SITE属于用户级,需要通过该模块的ENABLE_USER_SITE参数控制。如果USER_SITE仍然出现在sys.path前面,说明该参数未被正确设置,或者被USER_SITE目录下的配置文件覆盖。 - 虚拟环境配置文件:每个conda虚拟环境根目录下的
pyvenv.cfg文件包含include-system-site-packages选项,默认值为false,确保不加载全局系统级site-packages,但该选项不控制用户级的USER_SITE目录。
替代解决方案(无需删除USER_SITE目录)
如果不想删除AppData/Roaming/Python目录,可以通过以下方式修复:
- 激活虚拟环境后,执行
python -m site --user-site获取当前USER_SITE路径,在该路径下创建no-global-site-packages.pth空文件,强制Python优先加载虚拟环境的包。 - 激活虚拟环境时,设置环境变量
PYTHONNOUSERSITE=1,禁止Python加载用户级site-packages:set PYTHONNOUSERSITE=1 && conda activate pybert-tst
内容的提问来源于stack exchange,提问作者David Banas
相关产品推荐
相关产品推荐

