1. 先说结论:这个报错其实是在保护你的系统
最近帮几个朋友调环境,发现大家几乎都在同一个地方卡住:不管你是Windows用户开WSL2装Ubuntu,还是直接在实体机上装了新版本Ubuntu,只要想在系统Python里直接执行 pip install torch 或者 pip install vllm,十有八九会撞上那堵墙—— error: externally-managed-environment。这段报错一出来,很多第一次遇到的人直接懵了:以前明明都是pip install就完事,怎么换个系统版本就翻脸不认人了?
其实这不是系统在为难你,恰恰相反,是系统在保护你。这个报错的完整含义是“当前Python环境是外部管理的”,外部管理的“外部”指的是操作系统的包管理器,比如Ubuntu的apt、Fedora的dnf。你想,系统里很多关键工具都挂在Python下面,系统服务也依赖特定版本的Python包。如果pip不管三七二十一往里塞一个新版依赖,很可能把系统的依赖关系破坏掉,到时候连apt都跑不起来,只能重装系统。
这篇指南就是来帮你解决这个问题的。我会先把这个报错的前因后果讲透,然后给你在WSL2里从零到一搭建Ubuntu 22.04环境的完整流程,再给出PyTorch和vLLM这两个大家最常撞墙的包的具体安装步骤和参数选择,最后附上我自己实测踩过的坑和排查方法。不管你是第一次装深度学习环境的新手,还是被这个报错折磨了一下午的老手,这篇都能派上用场。
1.1 报错是怎么出现的,它到底在说什么
先看看典型场景。打开终端,进入一个全新的Ubuntu 22.04(升级到新Python版)或者23.04以上系统,输入:
bash复制pip install torch
然后看到非常长的一段“报错”:
text复制error: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
python3-xyz, where xyz is the package you are trying to
install.
If you wish to install a non-Debian-packaged Python package,
create a virtual environment using python3 -m venv path/to/venv.
Then use path/to/venv/bin/python and path/to/venv/bin/pip.
If you wish to install a non-Debian-packaged Python application,
it may be easiest to use pipx install xyz, which will manage a
virtual environment for you. Make sure you have pipx installed.
note: If you believe this is a mistake, please contact your Python
installation or OS distribution provider. You can override this,
at the risk of breaking your Python installation or OS, by passing
--break-system-packages.
hint: See PEP 668 for the detailed specification.
这个“报错”并不是告诉你pip坏了,而是pip在提示你:你现在用的这个Python环境,是由apt等系统工具管理的,你如果在里面硬塞第三方包,可能会破坏系统依赖。它甚至贴心地给出了三个替代方案:用venv建虚拟环境、用pipx装命令行工具、或者使用--break-system-packages冒险跳过。我建议你认真读一下这段提示,里面已经包含了正确的做法。
1.2 为什么Ubuntu 22.04之后突然变得“矫情”了
这个变化源于Python社区的PEP 668提案。PEP(Python Enhancement Proposal)是Python的改进提案,668号提案的核心思想是:把操作系统管理的Python环境标记为“外部管理”,这样pip在检测到这种标记后,就拒绝在没有明确许可的情况下往系统Python里装包。
从2023年以后,Ubuntu 23.04及以上版本默认在apt安装的Python中加入了EXTERNALLY-MANAGED标记文件,默认情况下pip安装到系统Python就会触发这个错误。而Ubuntu 22.04本身默认用的Python 3.10,虽然不一定自带这个标记,但如果你在22.04上更新了Python版本、用了PPA源、或者升级过pip,同样可能触发。所以标题里写“22.04+”其实覆盖的就是这一整片区域:22.04升级后的状态,23.04、24.04、24.10这些新版本,都会遇到这个问题。
可能有人会问,以前怎么没这么多事?因为以前pip确实可以随便往系统Python里装东西,装坏了只能靠用户自己扛。PEP 668把这个风险从机制上降低了——系统Python归系统管,用户的Python包归虚拟环境管,两边明确边界,这是Python生态往规范化走的一部分。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. WSL2环境准备:搭建一个能跑大模型的Linux环境
如果你和我一样平时主力机是Windows,那WSL2就是最方便的一条路。WSL2的全称是Windows Subsystem for Linux 2,它通过轻量级虚拟机运行原生的Linux内核,兼容性比WSL1好很多,而且支持GPU直通,可以在Windows下直接跑CUDA,这是很多人在Windows上做深度学习开发的首选方案。下面我把整个过程捋一遍。
2.1 检查WSL2是否就绪
刚接触WSL的朋友可能不知道,WSL有两个大版本:WSL1是API翻译层,WSL2是真正的虚拟机。安装PyTorch和vLLM一定要用WSL2,因为WSL1不支持GPU直通,很多CUDA相关的功能没法用。在Windows的CMD或PowerShell里执行:
powershell复制wsl --status
wsl -l -v
如果显示版本(VERSION)是2,说明已经是WSL2。如果显示1,需要转换:
powershell复制wsl --set-version Ubuntu-22.04 2
如果报错说没有启用虚拟化,先检查Windows功能。以管理员身份打开PowerShell,执行:
powershell复制dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
执行完重启电脑,然后设置默认版本:
powershell复制wsl --set-default-version 2
如果你还没有安装任何WSL发行版,直接用下面的命令安装Ubuntu 22.04:
powershell复制wsl --install -d Ubuntu-22.04
安装完打开Ubuntu的终端,先创建用户、设置密码。之后进入系统,第一件事是更新软件源和系统软件。这里多说一句:新安装的Ubuntu需要先执行apt update刷新索引,否则安装软件时会报找不到包。
2.2 配置WSL2的内存、CPU和GPU直通
WSL2默认分配的内存只有主机内存的50%左右,这对跑大模型来说可能不够。比如你Windows主机有32GB内存,WSL2默认可能只拿到16GB,如果模型加载到内存或者做量化推理,很容易OOM。推荐在 %UserProfile%\.wslconfig 文件里手动配置:
ini复制[wsl2]
memory=24GB
processors=12
swap=8GB
localhostForwarding=true
配置写好之后保存,在PowerShell里执行wsl --shutdown重启WSL使配置生效。memory设置要根据你实际的物理内存来,别设太高导致Windows本体卡顿。swap设置一个8GB左右的交换空间,可以在内存紧张时缓冲一下。
GPU直通这一点是WSL2吸引人的地方。只要Windows侧装了NVIDIA官方驱动,WSL2里不需要额外安装驱动,直接就能用GPU。验证方法是在WSL2终端执行:
bash复制nvidia-smi
如果你看到和Windows侧类似的GPU信息和驱动版本,说明直通正常。如果提示找不到nvidia-smi,大概率是Windows侧驱动版本太旧,更新驱动后重启WSL再试。
2.3 Ubuntu 22.04系统初始化
进入WSL2里的Ubuntu后,先更新:
bash复制sudo apt update && sudo apt upgrade -y
然后安装后续会用到的工具和Python组件:
bash复制sudo apt install -y python3 python3-venv python3-pip git curl wget build-essential
注意python3-venv一定不要漏,Ubuntu默认只带python3和pip,不一定带完整的venv模块。如果没装,后面创建虚拟环境会直接报“ensurepip is not available”之类的错误。build-essential是编译工具链,后面安装vLLM时编译优化器或flash-attn等C/C++扩展会用到。
3. 解决 externally-managed-environment 的三种方案,怎么选
报错信息里给了三条路:venv、pipx、--break-system-packages。我把它们的适用场景和坑一次说清楚。
3.1 标准方案:用venv虚拟环境隔离一切
最推荐的做法是创建虚拟环境。虚拟环境会把Python解释器和包管理完全隔离在一个目录里,在这个环境里pip可以随意安装,系统Python不受影响。
bash复制cd ~
python3 -m venv llm_env
source llm_env/bin/activate
激活后命令行提示符前面会出现 (llm_env),这时再安装任何包都不会撞上externally-managed-environment。要退出环境执行deactivate,要删除环境直接rm -rf llm_env,干干净净。
用venv有个需要接受的点:每次进入终端都要手动激活环境,或者把source ~/llm_env/bin/activate写进~/.bashrc。另外venv隔离的是Python包,不隔离系统库。如果系统本身缺CUDA库、缺libnccl,还是需要apt装,venv管不了这些。
3.2 命令行工具场景:用pipx更省心
如果只是想装一个命令行工具,比如vllm的CLI、haystack、jupyterlab这类,不想每次手动激活环境,pipx是更好的选择。pipx会为每个工具单独创建虚拟环境,并把可执行文件软链到~/.local/bin,这样你在任何目录都能直接使用。
bash复制sudo apt install pipx
pipx install vllm
pipx实际做的事情就是把venv、激活、维护PATH这些琐碎工作自动化了。它解决的问题是“我只想用命令,不想管环境”。不过pipx和venv也有一点区别:pipx装的东西入口是全局的,但依赖隔离在各自的虚拟环境里,互不干扰。如果同一个包不同项目需要不同版本,pipx就不太合适,还是用venv更灵活。
3.3 暴力方案:--break-system-packages的适用边界
报错提示里也写了,可以用这个参数强制绕过:
bash复制pip install torch --break-system-packages
加了这个参数,pip会无视系统的externally-managed标记,直接往系统Python里装包。这个方案我明确建议只在两种场景下用:一是临时测试容器,二是你知道自己在干什么、准备承担后果的个人测试机。生产服务器、日常开发主力机都不推荐。原因很简单:系统Python被破坏后,apt、系统工具、甚至桌面环境都可能挂掉,而排查这种问题往往比直接重装系统还痛苦。
3.4 为什么我坚持推荐虚拟环境
我在实际项目里见过太多次系统Python被搞挂的例子。最经典的一次是有人为了装一个模型部署工具,直接pip install把numpy从1.x升到2.x,结果系统里另一个依赖旧numpy的服务直接崩了,最后只能重装环境。有了PEP 668这层保护,至少机制上堵住了这种最危险的操作。
我的建议:只要你是用来做开发、跑模型训练或部署,一律用venv。它的成本低到几乎可以忽略,但带来的隔离性和可复现性是系统环境给不了的。你可以在一个环境里跑PyTorch 2.1,另一个环境里跑PyTorch 2.4,互相不干扰,这对模型迭代和对比实验来说真的太重要了。
4. 安装PyTorch:从版本选择到GPU验证
环境准备好之后,真正折腾的环节来了。PyTorch的安装本身不复杂,但版本选择直接影响后面能不能顺利用上vLLM,所以我把版本矩阵单独拿出来讲。
4.1 先定版本矩阵,再动手安装
PyTorch有CPU版和CUDA版之分,还有不同的CUDA编译版本。vLLM作为一个推理框架,对PyTorch的版本有严格的范围限制。如果先装了最新PyTorch,再装vLLM时很可能直接依赖冲突。所以顺序应该是:先看vLLM对外要求的PyTorch范围,再确定装哪个PyTorch版本。
以我写这篇文章时比较稳定的组合为例:
| 组件 | 推荐版本 |
|---|---|
| Python | 3.10 或 3.11 |
| CUDA | 12.1 |
| PyTorch | 2.3.1 |
| vLLM | 0.5.4 |
Python版本用3.10或3.11是最省心的,vLLM需要Python 3.8-3.12,但3.8太老、3.12太新,很多预编译包可能没跟上。CUDA版本建议用12.1,这是目前兼容性最好的档位,PyTorch和vLLM都提供很好的支持。如果你显卡驱动较新,选择12.1或12.4都行;如果显卡较老,可能要回退到11.8。
4.2 创建虚拟环境并安装PyTorch
进入虚拟环境:
bash复制source ~/llm_env/bin/activate
pip install --upgrade pip
安装PyTorch时,使用PyTorch官方源,并指定CUDA版本:
bash复制pip install torch==2.3.1 torchvision==0.18.1 torchaudio==2.3.1 --index-url https://download.pytorch.org/whl/cu121
安装时间取决于你的网络。如果一直超时,可以给pip加长超时时间,或者使用国内镜像。但要注意:使用镜像源时,--index-url必须指向包含CUDA版本whl的源,否则会默认装成CPU版。
4.3 验证CUDA和GPU是否真的可用
安装完成后,验证最关键的一步:
bash复制python -c "import torch; print('torch版本:', torch.__version__); print('CUDA可用:', torch.cuda.is_available()); print('GPU数量:', torch.cuda.device_count()); print('GPU型号:', torch.cuda.get_device_name(0))"
输出里torch.__version__如果带+cu121后缀,说明装的是CUDA 12.1版本;CUDA可用是True,GPU型号正确显示,说明GPU直通和CUDA都正常工作。如果输出False,先别急,按下面排查:
- 检查WSL2里nvidia-smi是否正常
- 检查Windows侧驱动版本是否太旧,更新到最新NVIDIA驱动
- 检查安装的PyTorch是不是CPU版(版本号没有+cu字样)
有一点需要强调:在WSL2里不要在Ubuntu内安装NVIDIA驱动,WSL2的GPU直通依赖Windows侧驱动,如果手贱在WSL2里装了linux版驱动,很容易把WSL2的GPU环境搞坏。
5. 安装vLLM:从依赖准备到首次推理
vLLM是我日常部署大模型最常用的推理框架。它主打高吞吐、显存高效,支持PagedAttention等优化,在长序列和并发场景下优势很明显。但安装它对环境有一定要求,下面把关键步骤和坑都写出来。
5.1 vLLM都有哪些依赖要求
vLLM不是一个轻量库,它需要:
- Python 3.8-3.12
- 支持CUDA的GPU(NVIDIA卡)
- CUDA >= 11.8
- GCC、make等编译工具链,因为安装时会编译部分CUDA扩展
- 足够的内存和显存
如果缺编译工具,编译阶段会报错。建议先安装:
bash复制sudo apt install -y build-essential cmake
还有一些隐性的系统库依赖,比如libnccl*,一般通过apt装(如果有需要的话)。
5.2 安装步骤与版本锁定
强烈建议在虚拟环境里安装,并且锁定版本,避免后续依赖悄悄变化:
bash复制pip install vllm==0.5.4
如果之前已经装了PyTorch,vLLM的依赖解析器会自动检测并尽量复用现有的torch版本。如果出现依赖冲突,比如“torch 2.4.0 is incompatible with vllm 0.5.4”之类的提示,优先调整PyTorch版本,而不是去改vLLM版本。因为vLLM的优化与特定PyTorch版本的API高度绑定,不太容易迁就旧版。
安装过程中vLLM会下载并编译一些东西,耗时比较长。如果网络不稳定,可以设置pip的--timeout参数,比如pip install --timeout 300 vllm==0.5.4。如果不想等编译,也可以考虑使用vLLM官方提供的Docker镜像,上手更快。
5.3 首次启动vLLM并调用推理接口
安装完成后,用一个小模型试一下。这里以Qwen2.5-7B-Instruct为例:
bash复制python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct \
--dtype float16 \
--gpu-memory-utilization 0.8 \
--port 8000
启动时把--gpu-memory-utilization设为0.8,意思是预留给模型的显存比例为80%,留一点余量给KV cache和上下文。当输出里出现类似:
text复制INFO: Started server process
INFO: Waiting for application startup.
INFO: Application startup complete.
说明服务启动成功。然后用curl测试接口:
bash复制curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-7B-Instruct",
"messages": [{"role": "user", "content": "你好,请介绍一下你自己"}]
}'
能正常返回JSON说明vLLM已经跑通了。如果只有CPU或者显存不够,可以改用更小的模型,比如Qwen2.5-1.5B,或者调整--gpu-memory-utilization。
6. 常见问题与排查技巧实录
下面这些坑都是我在实际安装和部署中遇到的,整理成速查表,方便你遇到问题直接照着查。
6.1 externally-managed-environment相关
| 问题 | 可能原因 | 解决办法 |
|---|---|---|
| 创建了venv但安装还报externally-managed-environment | 没有source激活环境,pip仍然指向系统pip | 执行which python确认路径,必须激活 |
