境全指南:venv、conda與版本管理實(shí)戰(zhàn))
做 Python 開發(fā)這些年虛擬環(huán)境這四個(gè)字幾乎每天都在打交道。venv、conda、還有 Python 版本選擇這三件事單獨(dú)拎出來都不難可一旦組合在一起坑一個(gè)接著一個(gè)。我在入行那會(huì)兒就吃過一次大虧同一臺(tái)開發(fā)機(jī)上跑兩個(gè)項(xiàng)目一個(gè)依賴新版數(shù)據(jù)處理庫(kù)另一個(gè)項(xiàng)目鎖死了舊版本接口全局環(huán)境里來回切換依賴折騰了兩天最后把系統(tǒng)自帶的 Python 環(huán)境徹底搞亂連 pip 都用不了。后來把虛擬環(huán)境這套東西從頭到尾研究明白才發(fā)現(xiàn)很多痛苦其實(shí)完全是可以提前避開的。這篇文章想把 venv、conda 和 Python 版本管理這三個(gè)話題揉碎了講清楚既給剛?cè)腴T的新手一條可以直接照做的路徑也幫用了很久但偶爾還會(huì)踩坑的老手做一次徹底的查漏補(bǔ)缺。1. 為什么需要虛擬環(huán)境從一次翻車現(xiàn)場(chǎng)說起1.1 全局安裝的隱患幾乎所有新手都會(huì)經(jīng)歷這樣一個(gè)階段拿到電腦裝好 Python然后不管什么項(xiàng)目一律 pip install 裝到全局。前兩個(gè)項(xiàng)目還好等第三第四個(gè)項(xiàng)目進(jìn)來問題就開始冒頭。我印象很深的一次經(jīng)歷是這樣的某模擬項(xiàng)目 X 需要舊版 Web 框架另一個(gè)項(xiàng)目則要求新版框架兩個(gè)項(xiàng)目涉及到底層依賴是同一套庫(kù)但接口差異很大。我在全局環(huán)境里把舊版升到新版項(xiàng)目 X 立刻跑不起來把新版降回舊版另一個(gè)項(xiàng)目又開始報(bào)錯(cuò)。那段時(shí)間每天都在來回改版本號(hào)最后連第三方庫(kù)之間的隱式依賴也跟著錯(cuò)亂整個(gè)環(huán)境基本報(bào)廢。這種局面就是典型的環(huán)境污染。不同項(xiàng)目對(duì)同一依賴的版本要求互相打架全局環(huán)境成了戰(zhàn)場(chǎng)。更麻煩的是很多庫(kù)向后不兼容今天升級(jí)完明天就不確定哪個(gè)項(xiàng)目會(huì)掛。再往后如果系統(tǒng)工具本身依賴 Python 的某個(gè)特定版本問題會(huì)更加棘手因?yàn)槟銊?dòng)任何一個(gè)項(xiàng)目的依賴都可能牽動(dòng)整個(gè)機(jī)器的運(yùn)行狀態(tài)。虛擬環(huán)境的意義就是為每個(gè)項(xiàng)目劃一塊獨(dú)立的區(qū)域各自維護(hù)各自的依賴版本互不干擾。今天給項(xiàng)目 A 裝什么包、升級(jí)什么版本項(xiàng)目 B 完全不受影響。這個(gè)隔離的思路是所有后續(xù)操作的基礎(chǔ)??炊诉@一點(diǎn)后面不管用 venv 還是 conda你都知道自己在做什么而不是機(jī)械地復(fù)制粘貼命令。1.2 虛擬環(huán)境的底層隔離原理虛擬環(huán)境說起來并不神秘。它本質(zhì)上就是在你的項(xiàng)目目錄下創(chuàng)建一個(gè)獨(dú)立的文件夾里面放著一份獨(dú)立的 Python 解釋器鏈接以及一份獨(dú)立的包安裝目錄。當(dāng)你激活環(huán)境后命令行里的 python 和 pip 都會(huì)優(yōu)先指向這個(gè)文件夾里的版本pip install 出來的包也會(huì)裝進(jìn)這個(gè)隔離目錄而不是全局的 site-packages。打個(gè)比方全局環(huán)境就像一棟共用廚房的公寓樓每個(gè)項(xiàng)目都在同一個(gè)廚房做飯調(diào)料互相混用。虛擬環(huán)境則是給每個(gè)項(xiàng)目單獨(dú)配了一套灶臺(tái)和調(diào)料柜你在這個(gè)灶臺(tái)炒菜再怎么放辣椒隔壁項(xiàng)目都不會(huì)被嗆到。這個(gè)類比雖然不是百分之百精確但用來理解隔離的核心思路足夠了。有了這層理解后面實(shí)際操作時(shí)就不會(huì)只是機(jī)械敲命令遇到異常也知道往哪個(gè)方向排查。比如環(huán)境壞了、包裝進(jìn)去了但 import 不到這類問題八成是解釋器路徑?jīng)]指向環(huán)境目錄而不是什么玄學(xué)故障。2. venv標(biāo)準(zhǔn)庫(kù)自帶的輕量方案2.1 創(chuàng)建與激活全流程venv 是 Python 3.3 之后內(nèi)置在標(biāo)準(zhǔn)庫(kù)里的模塊不需要額外安裝這也是它最大的優(yōu)勢(shì)。創(chuàng)建環(huán)境的命令極其簡(jiǎn)單在項(xiàng)目根目錄執(zhí)行python -m venv .venv這里的.venv是環(huán)境目錄的名字我習(xí)慣用點(diǎn)開頭的隱藏目錄既干凈又能避免跟項(xiàng)目文件混淆。命令執(zhí)行完目錄下會(huì)生成 binLinux/macOS或 ScriptsWindows目錄里面放著 activate 激活腳本、python 可執(zhí)行文件、pip 等。激活環(huán)境# Linux / macOS source .venv/bin/activate # Windowscmd .venv\Scripts\activate.bat # WindowsPowerShell .venv\Scripts\Activate.ps1激活成功的標(biāo)志是命令行提示符前面出現(xiàn)了(.venv)前綴??吹竭@個(gè)前綴就說明當(dāng)前 shell 會(huì)話已經(jīng)指向這個(gè)隔離環(huán)境了。之后你執(zhí)行 python、pip 都是在這個(gè)環(huán)境內(nèi)部安裝的包不會(huì)污染全局。退出環(huán)境用 deactivate 命令一條命令回到全局會(huì)話。這里多說一句Python 3.3 到 3.5 時(shí)代的 venv 功能偏弱當(dāng)時(shí)社區(qū)更推薦 virtualenv 這個(gè)第三方工具但從 3.6 開始venv 已經(jīng)足夠穩(wěn)定完全可以作為日常主力。如果你的 Python 版本還在 3.7 以下建議先把 Python 升級(jí)到 3.8 甚至更高再用 venv 會(huì)省心很多。2.2 requirements.txt 與依賴固化venv 本身只管隔離依賴記錄通常靠 requirements.txt 來完成。生成當(dāng)前環(huán)境的完整依賴列表pip freeze requirements.txt以后任何機(jī)器上需要復(fù)現(xiàn)這個(gè)環(huán)境只需要先創(chuàng)建 venv然后執(zhí)行pip install -r requirements.txt這里有一件非常重要的事pip freeze 默認(rèn)會(huì)把所有傳遞依賴依賴的依賴也列出來生成的文件可能很長(zhǎng)。我建議生成后人工檢查一遍明確哪些是直接依賴、哪些是傳遞依賴。如果項(xiàng)目依賴數(shù)量大也可以考慮用 pip-tools 這類工具去生成分層管理的依賴清單把直接依賴和傳遞依賴分開維護(hù)后期升級(jí)會(huì)更從容。如果項(xiàng)目的依賴?yán)锇恍┚幾g型庫(kù)直接 pip 安裝可能會(huì)現(xiàn)場(chǎng)編譯非常慢。解決辦法是優(yōu)先使用預(yù)編譯的 wheel 文件pip 默認(rèn)會(huì)優(yōu)先從 PyPI 拉取對(duì)應(yīng)平臺(tái)的 wheel這一步通常不需要額外配置。如果實(shí)在裝不上再考慮換 conda 環(huán)境后文會(huì)詳細(xì)講??傊畍env 加 requirements.txt 的組合是純 Python 項(xiàng)目里最通用、最不容易出錯(cuò)的搭配。2.3 venv 的幾個(gè)經(jīng)典坑venv 用起來簡(jiǎn)單但有幾個(gè)坑我踩過不止一次。第一個(gè)坑是激活后命令行找不到 python或者執(zhí)行的還是全局 Python。這通常是因?yàn)?shell 緩存了舊的命令路徑執(zhí)行hash -rLinux/macOS刷新緩存即可。Windows 上則要多留意某些終端工具會(huì)沿用上一次的 PATH 快照重啟終端頁(yè)面基本能解決。第二個(gè)坑是圖形界面程序里調(diào)用 Python 腳本時(shí)雙擊運(yùn)行的是關(guān)聯(lián)到全局解釋器的程序不會(huì)自動(dòng)帶上虛擬環(huán)境的解釋器。要在 GUI 場(chǎng)景下用虛擬環(huán)境里的 Python要么在腳本里顯式寫死 python 絕對(duì)路徑要么打包成可執(zhí)行文件不然就會(huì)出現(xiàn)在終端里能跑、雙擊就沒反應(yīng)的奇怪現(xiàn)象。第三個(gè)坑是 venv 環(huán)境跟著項(xiàng)目目錄走一旦項(xiàng)目文件夾被移動(dòng)或復(fù)制環(huán)境里的絕對(duì)路徑緩存就會(huì)失效。venv 目錄里有些文件寫死了原路徑移動(dòng)之后激活腳本會(huì)報(bào)錯(cuò)。我的習(xí)慣是環(huán)境壞了就直接刪掉重建反正有 requirements.txt重建一個(gè)環(huán)境就是兩三分鐘的事。第四個(gè)坑是不同 Python 版本之間的 venv 不能混用。用 3.8 創(chuàng)建的 venv即使你系統(tǒng)里裝了 3.11也不要指望這個(gè)環(huán)境自動(dòng)升級(jí)。萬(wàn)一換版本最靠譜的方式是對(duì)應(yīng)版本重新建環(huán)境再把依賴裝進(jìn)去。3. conda環(huán)境與包管理的全能選手3.1 conda 環(huán)境的創(chuàng)建與管理conda 是另一個(gè)思路它不只是一個(gè)虛擬環(huán)境工具更是一個(gè)完整的包管理器加環(huán)境管理器。安裝 Miniconda 或 Anaconda 之后你會(huì)擁有一個(gè)獨(dú)立的基礎(chǔ)環(huán)境然后可以在此基礎(chǔ)上衍生出任何項(xiàng)目環(huán)境。Miniconda 體積更小、更干凈我一般推薦從 Miniconda 開始。創(chuàng)建環(huán)境的基本命令conda create -n myenv python3.10這條命令會(huì)創(chuàng)建一個(gè)名為 myenv 的獨(dú)立環(huán)境并指定 Python 版本為 3.10。跟 venv 最大的區(qū)別是conda 環(huán)境默認(rèn)放在 conda 自己的安裝目錄下通常是 envs 目錄而不是跟著項(xiàng)目目錄走。這帶來一個(gè)實(shí)打?qū)嵉膬?yōu)點(diǎn)環(huán)境不依賴項(xiàng)目目錄移動(dòng)項(xiàng)目文件夾時(shí)環(huán)境依然有效。激活與退出conda activate myenv conda deactivate查看環(huán)境列表和刪除環(huán)境conda env list conda env remove -n myenv使用 conda 創(chuàng)建環(huán)境時(shí)我建議在創(chuàng)建命令里就帶上 python版本號(hào)。這樣能確保環(huán)境的 Python 版本精確可控避免后續(xù)因?yàn)榛A(chǔ)環(huán)境的 Python 版本不匹配而反復(fù)踩坑。新手最容易犯的錯(cuò)誤就是conda create -n myenv不帶版本參數(shù)結(jié)果環(huán)境沿用了基礎(chǔ)環(huán)境的 Python后面再想改版本就得重新建一個(gè)環(huán)境。3.2 conda 的包管理與 channel 機(jī)制conda 的包管理跟 pip 有本質(zhì)區(qū)別。pip 從 PyPI 拉包包內(nèi)容是源碼或 wheelconda 從自己的 channel軟件源拉包包內(nèi)容是編譯好的二進(jìn)制及其依賴樹。conda 解決依賴的方式更接近整體求解當(dāng)你執(zhí)行 conda install 的瞬間它會(huì)把整個(gè)依賴樹的兼容性問題一次性算清楚然后給出一個(gè)可以完整安裝的集合。這塊正是 conda 的優(yōu)勢(shì)所在。很多科學(xué)計(jì)算庫(kù)比如包含復(fù)雜編譯邏輯的數(shù)值計(jì)算庫(kù)和數(shù)據(jù)處理類庫(kù)在 PyPI 上安裝通常會(huì)觸發(fā)源碼編譯而在 conda 里直接就是預(yù)編譯好的二進(jìn)制包安裝速度非??彀姹炯嫒菪砸哺?。我自己在裝原生擴(kuò)展比較重的庫(kù)時(shí)會(huì)優(yōu)先用 conda 裝裝不上的再退回 pip。channel 的優(yōu)先級(jí)也值得注意。默認(rèn) channel 的訪問速度在國(guó)內(nèi)網(wǎng)絡(luò)環(huán)境下偏慢很多人會(huì)配置鏡像源。配置之后建議在項(xiàng)目環(huán)境內(nèi)執(zhí)行conda config --show channels確認(rèn)配置是否生效避免出現(xiàn)鏡像源失效后仍然從默認(rèn)源拉包的尷尬。另外conda 里面也可以用 pip 補(bǔ)裝 conda 沒有的包兩者共存沒問題。順序上有講究?jī)?yōu)先用 conda 裝conda 沒有的再用 pip 補(bǔ)。反過來操作偶爾會(huì)觸發(fā) conda 求解依賴時(shí)與 pip 已裝包沖突處理起來很繁瑣。3.3 conda 的適用場(chǎng)景與注意事項(xiàng)conda 適合哪些場(chǎng)景我最強(qiáng)烈的推薦是針對(duì)科學(xué)計(jì)算、數(shù)據(jù)分析、機(jī)器學(xué)習(xí)方向的項(xiàng)目。這些項(xiàng)目通常依賴數(shù)十個(gè)甚至上百個(gè)包包之間的版本約束極多用 conda 的依賴求解器能省下大量手工調(diào)試時(shí)間。我自己做數(shù)據(jù)類項(xiàng)目時(shí)幾乎默認(rèn)就開 conda 環(huán)境很少會(huì)遇到 pip 環(huán)境下那種裝 A 包把 B 包搞崩的情況。但 conda 也不是沒有缺點(diǎn)。環(huán)境整體體積偏大一個(gè)基礎(chǔ)環(huán)境動(dòng)輒幾個(gè) GB如果一臺(tái)機(jī)器上創(chuàng)建十幾個(gè) conda 環(huán)境磁盤空間會(huì)非常吃緊。解決辦法是盡量復(fù)用環(huán)境減少重復(fù)創(chuàng)建同時(shí)定期清理不再使用的環(huán)境和緩存文件。此外conda 環(huán)境里的 Python 跟純 Python 發(fā)行的 pip 包兩者安裝出的包放在不同的目錄體系里混用時(shí)要注意工具鏈的統(tǒng)一。如果某個(gè)包在 conda 里裝不上退到 pip 裝裝完確認(rèn) import 時(shí)拿到的是當(dāng)前環(huán)境里的版本而不是全局的。4. Python 版本選擇與管理4.1 為什么版本選擇這么重要聊完環(huán)境工具回到一個(gè)更上層的問題Python 版本到底怎么選版本選擇看起來只是數(shù)字差異實(shí)際上影響面非常廣。最直接的是語(yǔ)法兼容性某些新語(yǔ)法在舊版本上會(huì)直接報(bào)語(yǔ)法錯(cuò)誤。反向的兼容問題也很常見一些庫(kù)的新版本已經(jīng)放棄支持舊版 Python你如果還困在舊版環(huán)境里就只能一直用舊版庫(kù)拿不到新特性和安全修復(fù)。版本選擇還會(huì)直接影響你搭建本地開發(fā)環(huán)境的效率。如果你電腦上只裝了系統(tǒng)自帶的 Python版本往往跟著系統(tǒng)固定非常被動(dòng)。當(dāng)你需要為不同項(xiàng)目使用不同 Python 版本時(shí)就需要一個(gè)版本管理工具來幫你做切換。這也就是 pyenv 這類工具存在的核心原因。4.2 pyenv多版本管理的實(shí)用工具pyenv 是社區(qū)里最常用的 Python 多版本管理工具。它的核心邏輯是在你現(xiàn)有的基礎(chǔ)系統(tǒng)之上額外安裝多個(gè)指定版本的 Python然后在任意目錄下通過配置來決定當(dāng)前使用哪個(gè)版本。我的常規(guī)安裝流程大概是這樣的# 安裝 pyenvmacOS 用 HomebrewLinux 用官方腳本 # 然后安裝指定版本的 Python pyenv install 3.10.13 pyenv install 3.11.9 # 在項(xiàng)目目錄下指定版本 pyenv local 3.11.9執(zhí)行pyenv local 3.11.9之后當(dāng)前目錄會(huì)生成一個(gè) .python-version 文件只要進(jìn)入這個(gè)目錄python 命令自動(dòng)指向 3.11.9。移走這個(gè)文件目錄就回到全局默認(rèn)版本。這個(gè)機(jī)制配合 venv 使用非常舒服先由 pyenv 選好 Python 版本再用該版本創(chuàng)建 venv兩者各管一件事互不干擾。pyenv 的安裝過程有一點(diǎn)要注意它是通過源碼編譯 Python 的編譯依賴需要提前準(zhǔn)備好。如果在準(zhǔn)備系統(tǒng)庫(kù)時(shí)偷懶后續(xù)編譯過程中會(huì)不斷報(bào)錯(cuò)而且報(bào)錯(cuò)信息往往比較隱晦我見過不少同事卡在缺某個(gè)鏈接庫(kù)這一步。我的經(jīng)驗(yàn)是先按文檔把編譯依賴一次性裝齊再執(zhí)行安裝避免裝到一半卡殼。裝完用pyenv versions查看所有已安裝版本用pyenv global設(shè)置全局默認(rèn)版本。需要說明的是pyenv 的主要職責(zé)是管理解釋器版本并不負(fù)責(zé)隔離第三方庫(kù)。它跟 venv 是互補(bǔ)關(guān)系不是替代關(guān)系。把兩者搭配起來用才是完整的方案。4.3 不同項(xiàng)目的版本選型建議版本選擇沒有放之四海皆準(zhǔn)的標(biāo)準(zhǔn)但有一個(gè)比較實(shí)用的決策流新項(xiàng)目且團(tuán)隊(duì)沒有歷史包袱時(shí)優(yōu)先用當(dāng)前穩(wěn)定版本的最新版通常往前數(shù)一個(gè)版本以內(nèi)都可以。維護(hù)老項(xiàng)目時(shí)老老實(shí)實(shí)跟著項(xiàng)目現(xiàn)有版本走不要順手升級(jí)極容易引發(fā)依賴雪崩。機(jī)器學(xué)習(xí)或科學(xué)計(jì)算類項(xiàng)目往常用版本靠因?yàn)榫幾g型庫(kù)對(duì)新版本的支持往往會(huì)滯后幾個(gè)月到半年。純腳本工具、小型 Web 服務(wù)用穩(wěn)定版本即可不必追求最新。實(shí)際操作中我會(huì)先查一下項(xiàng)目主要庫(kù)的版本支持矩陣一般庫(kù)的文檔里都有再?zèng)Q定用哪個(gè) Python 版本。這個(gè)動(dòng)作十幾分鐘就能完成但能避免后續(xù)好幾天跟版本兼容性作斗爭(zhēng)。把選版本這個(gè)動(dòng)作前置是環(huán)境管理里最劃算的一筆投資。5. venv vs conda選型對(duì)比與決策建議5.1 六個(gè)維度全面對(duì)比很多新人糾結(jié)到底用 venv 還是 conda。這里不搞信仰之爭(zhēng)直接看對(duì)比表對(duì)比維度venvconda安裝成本Python 自帶零安裝需要裝 Miniconda/Anaconda體積較大環(huán)境位置項(xiàng)目目錄內(nèi)conda 的 envs 目錄Python 版本切換依賴系統(tǒng)已裝的版本創(chuàng)建時(shí)直接指定任意版本包安裝速度一般編譯型包可能慢科學(xué)計(jì)算類包更快預(yù)編譯依賴求解能力較弱pip 逐個(gè)解析較強(qiáng)整體求解環(huán)境體積小大適合場(chǎng)景通用 Python 開發(fā)、Web、腳本科學(xué)計(jì)算、數(shù)據(jù)、機(jī)器學(xué)習(xí)從表里能看出來兩者各有明確的主場(chǎng)。venv 輕、快、無依賴適合絕大多數(shù)日常 Web 開發(fā)和腳本項(xiàng)目conda 重、全、依賴管理強(qiáng)適合科學(xué)計(jì)算和數(shù)據(jù)方向。5.2 我的選型決策流程我自己在實(shí)際項(xiàng)目里通常這樣決策先判斷項(xiàng)目類型。如果項(xiàng)目是 Web 服務(wù)、API、爬蟲、自動(dòng)化腳本直接 venv如果是數(shù)據(jù)分析、機(jī)器學(xué)習(xí)、需要大量編譯型庫(kù)的項(xiàng)目直接 conda如果兩者邊界模糊我會(huì)選擇 conda 環(huán)境作為基礎(chǔ)再在需要時(shí)用 pip 補(bǔ)裝純 Python 包。第二個(gè)判斷點(diǎn)是團(tuán)隊(duì)協(xié)作。如果團(tuán)隊(duì)里已有統(tǒng)一的技術(shù)棧約定按約定來如果是自己開新項(xiàng)目就按上面的流程。團(tuán)隊(duì)協(xié)作場(chǎng)景下我特別建議把環(huán)境說明寫進(jìn)項(xiàng)目文檔比如用 requirements.txt 或 environment.yml注明 Python 版本和創(chuàng)建命令。環(huán)境本身不進(jìn)版本庫(kù)但環(huán)境的配方必須進(jìn)版本庫(kù)不然同事永遠(yuǎn)無法復(fù)現(xiàn)你的本地環(huán)境。需要強(qiáng)調(diào)的是選 venv 還是 conda 并不是非此即彼。同一臺(tái)機(jī)器上可以同時(shí)裝好 Miniconda 和系統(tǒng)自帶 Python項(xiàng)目各自用各自的環(huán)境彼此完全獨(dú)立。我自己就是這種混搭用法收益很大普通項(xiàng)目輕裝上路數(shù)據(jù)項(xiàng)目直接開 conda 環(huán)境兩邊互不干擾。6. 常見問題與排查技巧實(shí)錄6.1 激活失敗與路徑錯(cuò)亂情況一activate 腳本執(zhí)行后沒有任何反應(yīng)命令行提示符沒有變化。這種情況基本是執(zhí)行權(quán)限或者當(dāng)前 shell 類型不對(duì)。Linux 下先確認(rèn) activate 文件有執(zhí)行權(quán)限或者改用 source 方式執(zhí)行。Windows 下檢查是 cmd 還是 PowerShell兩套激活腳本不一樣用錯(cuò)了自然沒反應(yīng)。情況二激活后 python 版本還是全局的。檢查 PATH 順序確保環(huán)境目錄里的 bin/Scripts 目錄排在系統(tǒng)全局 Python 之前??梢杂脀hich pythonLinux/macOS或where pythonWindows查看實(shí)際調(diào)用的解釋器路徑一切以這個(gè)輸出為準(zhǔn)。別靠感覺判斷我見過太多人憑直覺以為激活成功結(jié)果一直在用全局環(huán)境。情況三從別的目錄激活環(huán)境環(huán)境找到了但 pip 提示找不到命令。大概率是環(huán)境所在目錄被移動(dòng)過pip 腳本里的路徑失效。直接用項(xiàng)目里的 requirements.txt 重建環(huán)境是最快的解法別試圖去修補(bǔ)腳本里的路徑不值得。6.2 包安裝與版本沖突排查包安裝慢是高頻問題。pip 默認(rèn)從官方源拉取某些網(wǎng)絡(luò)環(huán)境下經(jīng)??ǖ綉岩扇松?。解決辦法是配置鏡像源一次性寫入 pip 配置文件后續(xù)所有環(huán)境自動(dòng)生效。配置完以后用pip config list驗(yàn)證即可。版本沖突報(bào)錯(cuò)的信息一般都比較直白會(huì)明確指出哪兩個(gè)庫(kù)要求了互相矛盾的版本。我的排查順序是先看報(bào)錯(cuò)信息里指定的版本范圍再檢查當(dāng)前環(huán)境里已裝的版本最后決定是鎖定一個(gè)合理版本還是換用 conda 安裝。實(shí)在調(diào)不開時(shí)優(yōu)先查看該庫(kù)是否有更新的版本修復(fù)了兼容問題而不是盲目升級(jí)全環(huán)境。還有一種隱蔽的情況環(huán)境里明明裝了某個(gè)包代碼里 import 時(shí)卻提示找不到。先pip list確認(rèn)包確實(shí)在當(dāng)前環(huán)境再確認(rèn)運(yùn)行時(shí) python 解釋器確實(shí)是當(dāng)前環(huán)境的。很多時(shí)候是 IDE 或者終端沒有切換解釋器代碼跑到了全局環(huán)境而不是虛擬環(huán)境。這個(gè)排查動(dòng)作雖然簡(jiǎn)單但能省下大量抓瞎時(shí)間。6.3 環(huán)境的克隆、遷移與清理venv 環(huán)境想復(fù)制一份最穩(wěn)妥的方式是導(dǎo)出依賴清單再重建而不是直接復(fù)制目錄。conda 則提供了更直接的方式conda create -n newenv --clone oldenv這個(gè)命令會(huì)復(fù)制環(huán)境里的所有包省去重新下載的時(shí)間。不過它的前提是源環(huán)境本身是健康的如果源環(huán)境已經(jīng)損壞不如直接重建。清理長(zhǎng)期不用的環(huán)境也是必要的。venv 直接刪目錄即可conda 用conda env remove -n 環(huán)境名。另外conda 的緩存目錄可能積累好幾個(gè) GB定期用conda clean --all清理能釋放大量磁盤空間。多環(huán)境開發(fā)一段時(shí)間后花幾分鐘做一次環(huán)境體檢把不用的環(huán)境刪掉、把緩存清掉會(huì)讓你的開發(fā)機(jī)保持干凈利落的狀態(tài)。我個(gè)人在開發(fā)機(jī)上備著三套固定環(huán)境一套最新穩(wěn)定版 Python 搭配 venv 做日常小項(xiàng)目一套數(shù)據(jù)科學(xué)常用環(huán)境用 conda 維護(hù)一套專門用來測(cè)試舊版本兼容性。三套環(huán)境各司其職配合 pyenv 做版本切換幾乎再也沒有遇到環(huán)境失控的情況。虛擬環(huán)境這套工具鏈表面上是怎么裝環(huán)境的問題實(shí)際上解決的是怎么管理不確定性——依賴版本的不確定性、Python 版本的不確定性、團(tuán)隊(duì)環(huán)境的不確定性。把這套體系理順之后最大的收獲不是命令背得更熟而是再遇到莫名其妙的報(bào)錯(cuò)時(shí)第一反應(yīng)是冷靜分析原因而不是暴力重裝環(huán)境。如果你現(xiàn)在正被環(huán)境問題折磨得頭疼我的建議很簡(jiǎn)單先確定項(xiàng)目類型再選環(huán)境方案然后把環(huán)境配方寫進(jìn)文檔最后不要害怕刪掉環(huán)境重建。凡是幾分鐘能重建的東西都不值得你花幾天去修補(bǔ)。把依賴清單管好、把版本選型想清楚、把環(huán)境當(dāng)消耗品用這套思路能幫你少踩很多坑。這也是我從一堆失敗經(jīng)歷里總結(jié)出來的最值錢的一句話。