拓冰建站拓冰建站
首页 / 资讯中心 / 正文

uv虚拟环境管理实战:从创建到切换,告别Python环境混乱

如果你和我一样电脑里同时躺着好几个Python项目一个要3.8一个要3.11还有一个要3.12那过去的日子大概是这样的先去官网下载解释器再手工执行python -m venv接着激活环境然后pip install -r requirements.txt运气不好还会撞上某个依赖编译失败。这套流程我用了好多年直到换成uv才意识到虚拟环境管理本来可以更简单。这篇内容想把uv在虚拟环境上的核心用法完完整整串一遍venv创建、激活与切换、Python版本指定以及和PyCharm、VSCode这些编辑器的联动。无论你是刚接触Python的新手还是被环境问题折磨过的老手按下面的命令走一遍应该能省下不少时间。热词里频繁出现的“uv切换环境”“python虚拟环境迁移”“内网机器下载uv”这些场景文中也都会涉及。1. 从venv到uv为什么我放弃了一直用的组合拳1.1 传统虚拟环境的三个核心痛点先说痛点不然你不会理解为什么要换工具。第一个痛点是解释器版本管理。系统自带的Python通常只有一个版本但项目却经常要求不同的Python。有人用pyenv有人手动去官网下载安装包装完还要自己记住路径时间一长机器上的Python版本乱得像一锅粥。第二个痛点是依赖安装慢。pip install -r requirements.txt对于小项目还行遇到那种几十个依赖的项目等待时间能被拉得很长中间还经常出现网络超时、依赖冲突。更麻烦的是它不会帮你锁住完整依赖树昨天还能跑的项目今天重装环境可能就起不来了。第三个痛点是“激活环境”这件事本身。Windows和Linux的激活命令不一样普通用户容易在PowerShell执行策略、PATH顺序上踩坑。有时候辛辛苦苦建好环境隔两周再打开终端已经忘记该source哪个目录了。1.2 uv把哪些原本分离的工作合并了uv最大的价值是它把“Python解释器下载”“虚拟环境创建”“依赖安装”“依赖锁定”这几件事合并到了一个工具里。过去我要为某个项目准备一套环境至少需要三步先装解释器再建venv最后激活并装包。uv出现后这套流程被压缩成了两条命令uv venv --python 3.12和uv run。我用一个对比表格来说明它和传统工具的区别功能venv pipcondauv创建虚拟环境python -m venv .venvconda create -n envuv venv指定Python版本需要先手动安装conda create -n env python3.12uv venv --python 3.12依赖安装速度串行下载较慢取决于channel并行下载 全局缓存明显更快依赖锁定无内置锁文件一般靠手工导出自动生成uv.lock解释器下载不管通过conda源管理uv python install 3.12直接管激活依赖需要手动activate需要手动activateuv run可以跳过激活步骤1.3 uv快不只是因为用了Rust很多人说uv快是因为Rust写的这个说法对了一半。Rust让它启动开销低但真正让安装变快的是设计上的优化它默认采用并行下载同时依赖一个全局缓存目录同一个包在不同项目里不需要反复从网络拉取。再加上它一次性解析完整依赖树并写入uv.lock后面任何一次同步都只需要按照锁文件执行不会每次重新碰运气。这里也解释了为什么团队协作时uv很值钱新同事拿到项目只要机器上有uv一条uv sync就能把环境还原到和你完全一致的状态。这个优势在“虚拟环境迁移”场景下特别明显不需要再靠requirements.txt去猜依赖版本。2. 安装uv从一键命令到离线分发不同环境的落地方案2.1 在线环境Windows、Linux、macOS各有各的装法uv的安装方式非常灵活推荐的做法是直接使用官方提供的安装脚本。Windows下打开PowerShell执行powershell -ExecutionPolicy ByPass -c irm https://astral.sh/uv/install.ps1 | iexLinux或macOS下在终端执行curl -LsSf https://astral.sh/uv/install.sh | sh不想用脚本也没问题因为uv本身发布在PyPI上所以也可以当普通Python包来安装pip install uvmacOS用户还可以用Homebrewbrew install uvWindows用户如果装了winget也可以winget install --id astral-sh.uv我的建议是优先用官方脚本因为它会把uv装到一个独立目录并且把二进制放到PATH里。如果你用pip install uv那说明你的机器上已经存在一套Python环境这与uv想解决的“先有鸡还是先有蛋”问题有点冲突——我们想用uv来管理Python结果还要先靠Python装uv。2.2 离线和内网机器怎么装uv热词里频繁出现“内网机器下载uv”“ubuntu离线安装uv”这确实是很多人会撞上的场景。内网机器通常没有办法直接访问下载地址解决方案的关键在于uv本身是一个编译好的单文件二进制不像很多工具需要一堆运行时依赖。具体操作分两步。第一步在一台能联网的机器上去uv的GitHub Releases页面下载对应平台、对应架构的压缩包。比如Linux x86_64就下载uv-x86_64-unknown-linux-gnu.tar.gzWindows就下载对应的zip包。第二步把压缩包拷到内网机器上解压后把里面的uvWindows下是uv.exe放到一个已经在PATH里的目录比如/usr/local/bin或C:\Windows\System32。然后在终端验证uv --version能输出版本号就说明安装成功。这种方式不需要安装任何额外依赖非常干净。如果你在内网机上已经有Python环境更简单的方式是在联网机器上执行pip download uv -d ./packages再把packages目录整个拷到内网内网执行pip install --no-index --find-links./packages uv实测下来前一种方式更适合“内网机器本身干净”的场景而后一种方式适合那些已经在用pip管理工具链的团队。2.3 装完提示“uv不是内部或外部命令”的真相这个问题出现频率极高。安装脚本并不会把uv放到Windows已经默认存在的PATH目录而是装到用户目录下比如C:\Users\你的用户名\.local\bin或者%USERPROFILE%\.local\bin。脚本结束时如果检测到这些路径不在PATH里会提示你手动添加很多人没注意就直接关掉终端重新打开之后自然找不到命令。解决方法有两个自己把~/.local/bin加入PATH或者干脆重新开一个终端再试一次。macOS和Linux下通常是~/.local/bin如果你用Homebrew装的则不需要关心这个。3. uv venv创建虚拟环境常用参数和目录行为3.1 最基础的创建行为在任意项目目录下执行uv venvuv会在当前目录创建一个.venv文件夹并输出类似下面的信息Using CPython 3.11.9 Creating virtual environment at: .venv创建完成后虚拟环境的本体就在项目文件夹里路径是.venv。很多人问“虚拟环境建到哪里去了”答案就在这里它没有注册到任何全局列表里本质就是一个文件夹。这个思维很重要它意味着删除环境直接删掉.venv目录即可不需要像conda那样专门执行conda env remove。如果你不想用默认的.venv目录名也可以指定路径uv venv myenv这会在当前目录下生成myenv文件夹。不过我不建议这么做因为uv很多命令默认会去寻找项目下的.venv用自定义路径反而会让后续操作变得别扭。3.2 指定Python版本--python参数的几种写法uv venv最实用的地方在于可以直接指定Python版本uv venv --python 3.12这个命令的意思是用3.12版本的解释器创建虚拟环境。注意它不仅仅是把一个3.12的解释器路径塞进环境里而是会先检查本机有没有3.12如果没有会给出类似“Python 3.12 not found”的提示。如果你的机器上已经通过uv安装过多个Python版本还可以用更精确的方式uv venv --python 3.11 uv venv --python 3.12.4 uv venv --python pypy3.10甚至可以用范围表达式uv venv --python 3.10,3.12这种范围写法在多个Python版本并存时非常实用uv会自己挑一个符合条件的最新版本。如果你最终想确定到底用了哪个版本创建完成后执行.venv/bin/python --versionWindows下执行.venv\Scripts\python.exe --version这里需要提醒一下uv venv在本地找不到指定版本时不会像uv run那样主动下载。所以实操中更顺手的组合是“先uv python install 3.12再uv venv --python 3.12”具体在第五章展开。3.3 --seed和--system-site-packages两种不常用但能救场的参数uv设计的目标是快所以它创建的虚拟环境默认不带pip。这通常是好事因为uv有自己的一套依赖安装命令。但有些老项目、老脚本必须依赖pip或者你想在虚拟环境里执行pip install这时创建时加一个--seed参数即可uv venv --seed加上之后虚拟环境里会预装pip、setuptools和wheel相当于补齐了venv默认行为。另一个参数是--system-site-packagesuv venv --system-site-packages加了它之后虚拟环境会“继承”系统Python环境里的已安装包。什么时候会用到呢比如你在一台内网机器上系统Python里已经装了大量依赖但你又不想花时间在虚拟环境里重新装一遍这时候可以让虚拟环境直接看到系统包。代价是隔离性变差容易搞不清某个包到底是环境里的还是系统里的除非有很强的理由否则我不建议日常使用。3.4 Windows路径带空格一个让人头疼的老问题热词里有一条特别具体的信息d:\python project\.venv\scripts\python.exe d:\python project\main.py did。一看就知道是Windows路径带空格导致的执行报错。问题的根源是命令行解析规则。如果你直接执行d:\python project\.venv\Scripts\python.exe d:\python project\main.py系统会把命令拆成d:\python和project\.venv\Scripts\python.exe等几段然后报“d:\python 不是内部或外部命令”。正确的做法是整个路径加双引号d:\python project\.venv\Scripts\python.exe d:\python project\main.py但如果你每天都这么敲体验确实很差。更好的办法是进入项目目录后直接执行uv run python main.py这样根本不需要关心解释器路径uv会自动定位到.venv里对应的解释器。关于uv run的详细用法下一章会重点讲。4. 激活、退出与“不激活也能用”的切换逻辑4.1 Windows下的激活命令和那些经典报错Windows环境下进入项目目录后常规激活命令是.venv\Scripts\activate等一下这个命令在cmd里和PowerShell里的表现不完全一样。在cmd里直接执行activate.bat.venv\Scripts\activate.bat在PowerShell里应该执行activate.ps1.venv\Scripts\Activate.ps1最常见的报错是无法加载文件 .venv\Scripts\Activate.ps1因为在此系统上禁止运行脚本这是PowerShell执行策略的限制。如果你确定当前项目的脚本是安全可信的可以为当前用户放开限制Set-ExecutionPolicy RemoteSigned -Scope CurrentUser如果公司电脑有统一策略限制改不了那就退回cmd窗口用activate.bat激活或者干脆用后面的uv run方案。4.2 Linux/macOS下的激活命令Linux和macOS下就简单多了source .venv/bin/activate激活成功后终端提示符前面会出现(.venv)前缀这时你再执行python系统会优先使用虚拟环境里的解释器。离开环境用deactivate这里有一个非常容易被新手忽略的点source命令只在当前终端会话生效关掉这个终端下次打开还得重新激活。很多人因此忘了激活、装包装到系统环境里最后搞得一团糟。4.3 更推荐的用法uv run与uv shell跳过手动激活uv的设计者和传统venv有一个重要分歧他们认为显式激活这个动作本身就是多余的心智负担。所以uv提供了两个更省事的命令uv run python main.py这个命令的运行逻辑是在项目目录下检测是否存在.venv不存在则创建然后直接在虚拟环境里执行后续命令。加了--python参数还能临时用指定版本uv run --python 3.12 python main.py如果你就是想进入一个已经激活的交互式shell可以用uv shell它会让你进入当前项目的虚拟环境shell效果等同于手动source .venv/bin/activate。我从实际使用的感受来讲日常开发uv run比手动激活舒服太多。它不用考虑“我现在在哪个终端”“环境是否已经激活”这些问题项目目录下直接跑命令永远不会搞混。4.4 切换Python版本时的环境重建热词里有“uv 切换环境”和“uv 删除环境”这两个操作经常和版本切换绑在一起。当你在项目根目录执行uv python pin 3.11uv会在项目下生成一个.python-version文件这就是告诉uv这个项目以后用3.11。但这并不会把已经创建好的.venv自动升级成3.11你在命令行里敲uv run python --version会看到一个现象任务规划器里的版本已经变成了3.11的约束但现有环境里的解释器可能还是旧的3.12。要彻底切换最稳妥的做法是重建环境。先删掉旧环境Remove-Item -Recurse -Force .venv # Windows PowerShell rm -rf .venv # Linux/macOS然后重新创建并同步uv venv --python 3.11 uv sync这个“删除环境、重建环境”的思维在uv里很自然因为.venv只是一个文件夹删掉重来通常只需要几秒钟。相比conda的环境导出、导入这种方式干净且没有残留。遇到环境疑似损坏时我的第一反应也是删掉重建而不是去翻那些排查教程。5. 让uv来管理Python解释器版本指定从入门到实用5.1 为什么要让uv管理解释器Python版本管理的痛点往往在“第一台机器上没问题换台机器就出事”。原因大多是解释器版本不一致。uv的解法是让解释器本身也成为“项目管理的一部分”。在uv的体系里你不需要先装好Python再创建环境而是可以让uv负责解释器的安装。最直接的好处是可以同时管理3.10、3.11、3.12等多个版本每个项目各取所需互不干扰。5.2 常用命令list、install、uninstall、find、pin先看本机有哪些Python可用uv python list这个命令会同时列出已安装的版本和可以下载安装的版本。想安装某个版本uv python install 3.12如果你希望装一个最新补丁版uv python install 3.11uv会自动解析到当前3.11系列的最新补丁版本。反过来想卸载uv python uninstall 3.12想查看当前项目最终会用哪个Python可以用uv python find这个命令不是猜的它会根据.python-version、pyproject.toml里的requires-python字段、以及.venv当前使用的解释器综合判断。排查问题时uv python find能帮你快速定位“为什么用的是这个版本”。钉住项目版本用uv python pin 3.115.3 .python-version文件让版本约束跟着项目走uv python pin 3.11会生成一个.python-version文件内容很简单就是一行3.11。这个文件最好提交到Git里这样所有拿到项目的同事只要执行uv runuv就会自动识别并切到3.11。这里有一个组合用法值得记住项目根目录有.python-version里面写3.11然后在pyproject.toml里声明requires-python 3.10,3.12。那么uv会优先参考.python-version的精确指定同时用requires-python校验这个选择是否符合项目声明。两者配合团队里再也不会出现“我本地能跑你本地不能跑”的经典矛盾。5.4 离线环境的版本管理建议内网环境想直接让uv下载Python解释器通常是做不到的因为Python安装包默认从Python官网拉取。有两条路可以绕第一条如果你内网系统里已经预置了某个Python版本可以让uv把它当成受管理的解释器来用。uv支持把系统Python链接进自己的管理目录相关思路可以在uv python install --help里查--link-system-python选项。不同版本参数略有差异建议以你安装的版本帮助输出为准。第二条在联网机器上用uv python install 3.12装好然后把uv负责解释器的缓存目录整个拷贝到内网机器同时把内网的UV_PYTHON_INSTALL_DIR环境变量指到对应位置。这条操作对缓存目录的路径要求比较高适合团队内统一运维的场景平时单机使用不必折腾。6. 和PyCharm、VSCode联动以及脚本调用不再报错6.1 在PyCharm里选择uv创建的环境PyCharm的新版和旧版界面略有差异但逻辑一样安装完依赖后在Settings里进入项目解释器配置。路径通常是File - Settings - Project: 你的项目名 - Python Interpreter点击右侧的齿轮或“Add Interpreter”选择“Existing environment”然后在解释器路径里浏览到项目下的.venv\Scripts\python.exeWindows或.venv/bin/pythonLinux/macOS。在这个界面里很多人会误选到.venv文件夹根目录那个不是解释器PyCharm也不会接受。记得选到具体的python.exe或python文件。6.2 在VSCode里选择uv创建的环境VSCode需要先安装Python扩展然后用快捷键打开命令面板快捷键CtrlShiftPWindows/Linux或CmdShiftPmacOS输入Python: Select Interpreter在列表中选择.venv对应的解释器路径即可。如果列表里没出现可以点击“Enter interpreter path”手动浏览到.venv\Scripts\python.exe。这里有个经验VSCode一旦选择了某个解释器会在项目根目录生成.vscode/settings.json把该路径写进去。如果你的项目换机器后路径变了记得更新这个文件或者重新选择一次否则VSCode会一直指向老路径。6.3 路径带空格的正确调用姿势回到热词里那条Windows报错信息你注意到没有用户其实是想直接用解释器路径运行脚本但因为路径里有空格命令被拆断。正确写法是每个路径单独加双引号 d:\python project\.venv\Scripts\python.exe d:\python project\main.py在cmd里可以不加PowerShell里建议加。不过以我现在的习惯这种场景我会直接cd d:\python project uv run python main.pyuv run会自己找到.venv里的解释器完全绕开路径空格问题。这也是我在团队内部推广uv时最爱展示的一个细节——“你不用关心解释器在哪只要你人在项目目录里uv就知道该干什么”。6.4 uv run --with临时依赖适合调试和一次性脚本还有一个很实用的场景你手上有一个Python脚本需要依赖某个库但你不想为它专门创建环境也不想污染当前环境。看这个uv run --with requests python fetch_data.pyuv会临时创建一个包含requests的隔离环境执行完这个命令后环境自动丢弃。对于写爬虫脚本、写临时分析脚本的场景这个能力比手工创建环境高效太多。7. 我实际踩过的坑和排查思路7.1 activate.ps1无法加载提示“禁止运行脚本”这是Windows用户最常见的第一个坑。根本原因是PowerShell默认不允许执行本地脚本。处理办法前面提到过给当前用户放开RemoteSigned策略Set-ExecutionPolicy RemoteSigned -Scope CurrentUser如果你不想到处折腾执行策略也可以用cmd来激活或者执行powershell -ExecutionPolicy ByPass -c .\.venv\Scripts\Activate.ps1但最省心的还是把激活这件事交给uv run。7.2 明明激活了环境python却还是系统版本这个现象通常发生在你执行激活命令之后发现python --version显示的是系统Python或其他环境里的版本。排查链路是先确认当前虚拟环境里有没有pythonls .venv/bin/pythonWindowsdir .venv\Scripts\python.exe如果文件存在再看环境变量echo $env:PATHLinux/macOSecho $PATH看.venv相关路径是不是在最前面。如果不在很可能是激活脚本没有生效或者你开了多个终端当前终端没有source到新的环境。我见过不少人是在VSCode的集成终端里同时开了好几个标签页激活了A标签却在B标签里执行python自然还是老版本。7.3 uv sync和pip install混用环境状态乱了装了uv之后我一度在同一个项目里一会儿用uv add一会儿又顺手pip install某个包结果发现uv run检测到的依赖和实际site-packages里的内容对不上。原因是uv的依赖状态是通过uv.lock和pyproject.toml来维护的pip install直接往site-packages里塞的包并不在锁文件里。下次uv sync时多出来的包会被清掉项目就跑不起来了。教训很简单项目用了uv就统一用uv add、uv remove、uv sync来维护依赖不要混用pip。如果已经有老项目依赖requirements.txt可以用uv pip install -r requirements.txt过渡但长期来看还是迁移到uv的依赖管理模型更省心。7.4 缓存目录占用空间越来越大uv有全局缓存装过的每个包都会留在缓存里方便以后复用。在实际使用中这个目录会慢慢变大尤其当你频繁切换Python版本、尝试不同包时。查看缓存位置uv cache dir清理没用的缓存uv cache prune清空全部缓存uv cache cleancache prune比cache clean温和它只删掉那些不再有环境引用的缓存包不会影响已创建的环境。建议日常用prune就够。7.5 一直提示找不到指定的Python版本如果你的项目根目录有.python-version文件并且里面写了一个本地没有装的版本那么任何时候执行uv run或uv venv --python xxx都会报“找不到版本”。处理方式是先看看当前钉住的版本cat .python-version然后再安装对应版本或者改成你本地已有的版本uv python install 3.12还有一种情况是pyproject.toml里写了requires-python 3.13但你的机器上根本没装3.13uv也会提示找不到。处理方式一样装一个能满足约束的版本即可。这个检查逻辑很容易记住uv不会在你毫不知情的情况下偷偷下载解释器它默认遵循文件里的约束当约束和实际环境不一致时它会明确报错。这时候不要想着绕开它老老实实把对应版本装好才是正路。个人体会切换到uv之后我最大的收获其实不是速度本身而是对虚拟环境这件事的理解变了。过去我觉得环境是一个需要小心伺候的、很容易出问题的东西现在我只把它当成一个普通的文件夹——坏了删掉重建几秒钟搞定完全不心疼。所有和Python版本相关的决策都被固化到了.python-version和pyproject.toml里换一台机器、换一个同事来接手成本都低很多。最后分享一个小技巧如果你在Windows上经常被路径空格、激活脚本折腾不妨养成一个习惯所有Python项目目录都用一个不带空格的短路径比如E:\projects\demo。很多玄学问题会直接消失。然后日常命令统一用uv run需要进交互式调试再用uv shell这样你既能享受虚拟环境的隔离性又不用背着激活脚本那套繁琐的心智负担。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门