
簡(jiǎn)介matplotlib-3.7.0.tar.gz是Python數(shù)據(jù)可視化基石庫(kù)matplotlib的完整源代碼包適合需要深入掌握繪圖原理的開(kāi)發(fā)者、數(shù)據(jù)科學(xué)家與科研人員用于離線安裝、二次開(kāi)發(fā)或?qū)W習(xí)其內(nèi)部實(shí)現(xiàn)。包內(nèi)共2000個(gè)文件以908個(gè)Python源文件為核心輔以611個(gè)PDF文檔、160個(gè)頭文件、107個(gè)PNG示例圖以及CPP/SVG/TXT等資源共34.66MB可滿足源碼閱讀、文檔查閱和示例復(fù)現(xiàn)的多重需求。已有192人瀏覽學(xué)習(xí)資源覆蓋從基本概念、pyplot接口、各類型圖表繪制到自定義屬性、子圖布局、保存與交互等完整知識(shí)鏈條。下載后可獲得完整的庫(kù)源碼、官方文檔與示例圖像既能直接進(jìn)行本地部署也能對(duì)照源碼理解matplotlib的渲染機(jī)制與擴(kuò)展方式為后續(xù)數(shù)據(jù)可視化開(kāi)發(fā)提供堅(jiān)實(shí)基礎(chǔ)。1. matplotlib 3.7.0 源碼包安裝為什么一句話能裝的庫(kù)偏要手動(dòng)編很多開(kāi)發(fā)者看到 matplotlib-3.7.0.tar.gz 的第一反應(yīng)是這東西不是 pip install 一步就能裝完嗎確實(shí)日常開(kāi)發(fā)里一句話就夠但當(dāng)你拿到的是源碼包而不是編譯好的 wheel 時(shí)事情就變得微妙。這個(gè)版本要求 Python 3.8 以上的解釋器編譯環(huán)節(jié)要依次找到 numpy 頭文件、FreeType 和 libpng 的庫(kù)文件任何一環(huán)缺失都會(huì)在構(gòu)建階段直接翻車。這篇記錄寫(xiě)給兩類人一類是拿到 tar.gz 卻不敢下手的初學(xué)者另一類是生產(chǎn)環(huán)境離線安裝時(shí)被依賴列表搞到頭大的運(yùn)維同行。按這套流程走一遍你會(huì)發(fā)現(xiàn)自己不僅裝好了這個(gè)版本還把它背后的依賴關(guān)系徹底理清了。2. 裝前準(zhǔn)備Python 版本、編譯工具鏈與依賴庫(kù)三項(xiàng)檢查源碼安裝最反直覺(jué)的一點(diǎn)是百分之九十的失敗不是編譯過(guò)程出錯(cuò)而是開(kāi)始之前環(huán)境就沒(méi)準(zhǔn)備好。我在實(shí)際環(huán)境里裝過(guò)好幾個(gè)需要本地編譯的包幾乎都掛在同一類問(wèn)題上——缺了某個(gè)頭文件或者當(dāng)前 python3 指向的解釋器不是你以為的那個(gè)。準(zhǔn)備工作可以拆成三項(xiàng)硬檢查每一項(xiàng)都對(duì)應(yīng)后面某個(gè)具體環(huán)節(jié)省得到時(shí)候日志刷出一片紅色再回頭補(bǔ)救。2.1 確認(rèn) Python 版本3.7.0 要求解釋器 3.8 以上matplotlib 3.7.0 的 setup.py 里對(duì) Python 解釋器的要求是 3.8 及以上。這個(gè)限制不是隨便寫(xiě)的源碼包里的 C 擴(kuò)展和部分生成代碼用到了新版本解釋器才有的 APIPython 3.6 或 3.7 上編譯可能在很早期就直接退出。對(duì)比一下pip 直接裝 wheel 的時(shí)候反而沒(méi)這么敏感因?yàn)?wheel 是預(yù)先編好的二進(jìn)制解釋器兼容性已經(jīng)固化在包里源碼包是到你的機(jī)器上現(xiàn)編解釋器的頭文件路徑和特性集直接決定成敗。python3 --version python3 -c import sys; print(sys.executable)第一條命令看版本號(hào)第二條看解釋器的絕對(duì)路徑。我習(xí)慣兩條都跑因?yàn)橛行C(jī)器的 python3 被軟鏈到了別的目錄你以為是系統(tǒng)自帶的其實(shí)是后來(lái)手動(dòng)安裝的另一套解釋器。接著確認(rèn) pip 和解釋器配對(duì)python3 -m pip --version這里務(wù)必用 python3 -m pip 而不是裸 pip。裸 pip 的 shebang 指向哪個(gè)解釋器不直觀經(jīng)常出現(xiàn) pip 裝完、import 時(shí)卻找不到的尷尬情況。判斷配對(duì)的標(biāo)準(zhǔn)很簡(jiǎn)單python3 --version 和 python3 -m pip --version 兩個(gè)命令輸出里體現(xiàn)的解釋器信息應(yīng)一致。版本不滿足 3.8 的話先換解釋器再繼續(xù)別在老版本上硬編后續(xù)編譯報(bào)錯(cuò)會(huì)非常難排查。2.2 編譯工具鏈gcc、g 和 Python 開(kāi)發(fā)頭文件缺一不可matplotlib 的核心繪圖模塊有一批 C/C 擴(kuò)展包括路徑計(jì)算、圖像讀寫(xiě)等模塊安裝過(guò)程必須把它們就地編譯出來(lái)。這一步需要兩類東西編譯器和 Python 開(kāi)發(fā)頭文件。沒(méi)有頭文件時(shí)報(bào)錯(cuò)通常會(huì)指向 Python.h: No such file or directory切到構(gòu)建日志頁(yè)面一眼就能看到。gcc --version which gcc g make ls /usr/include/python3.* 2/dev/null || echo no python dev headers第一行確認(rèn) C 編譯器存在第二行把 gcc、g、make 三個(gè)一起查第三行查 Python 頭文件。為什么專門強(qiáng)調(diào) g因?yàn)?matplotlib 的依賴?yán)锬承┯?jì)算庫(kù)是 C 實(shí)現(xiàn)的只裝 gcc 不裝 g編譯到對(duì)應(yīng)依賴時(shí)會(huì)突然斷掉。find /usr/include/python3.* 是看頭文件目錄是否存在命名格式通常是 /usr/include/python3.9版本號(hào)和后綴跟著解釋器走。在 apt 系的發(fā)行版上缺工具鏈的標(biāo)準(zhǔn)處理是安裝 build-essential 和 python3-dev 兩個(gè)包在 yum/dnf 系發(fā)行版上對(duì)應(yīng) gcc、gcc-c 和 python3-devel。容器鏡像最容易缺這塊很多精簡(jiǎn)鏡像只有運(yùn)行時(shí)沒(méi)有編譯環(huán)境which 那行命令沒(méi)有任何輸出就是明確信號(hào)。提示python3-dev 的版本必須與當(dāng)前解釋器嚴(yán)格對(duì)應(yīng)。解釋器是 3.9就裝 python3.9-dev否則頭文件路徑對(duì)不上編譯照樣掛。2.3 第三方依賴清單numpy、FreeType、libpng 缺哪個(gè)都編不過(guò)這是源碼安裝最容易被低估的一環(huán)。matplotlib 的編譯期依賴分兩類一類是 Python 層的包比如 numpy、kiwisolver、cycler、pyparsing、python-dateutil在 setup.cfg 的 install_requires 里能看到聲明另一類是系統(tǒng)級(jí)庫(kù)FreeType 和 libpng它們以動(dòng)態(tài)庫(kù)文件形式存在于系統(tǒng)目錄包管理工具管不到它們。缺了這些編譯都會(huì)在對(duì)應(yīng)環(huán)節(jié)報(bào)頭文件找不到的錯(cuò)誤。下面這張表是我常用的核對(duì)依據(jù)按缺失時(shí)的報(bào)錯(cuò)信息反查很方便依賴項(xiàng)類型編譯期作用缺失時(shí)的典型報(bào)錯(cuò)numpyPython 包C 擴(kuò)展排版和數(shù)組運(yùn)算numpy/arrayobject.h: No such file or directoryFreeType系統(tǒng)庫(kù)字體渲染ft2build.h not foundlibpng系統(tǒng)庫(kù)PNG 圖像輸出png.h not found檢查命令python3 -c import numpy; print(numpy.__version__) ldconfig -p | grep -E freetype|libpng第一行確認(rèn) numpy 已裝好且能被當(dāng)前解釋器導(dǎo)入。matplotlib 3.7.0 對(duì) numpy 有版本下限要求具體數(shù)值以源碼包里的說(shuō)明為準(zhǔn)我的經(jīng)驗(yàn)是 1.20 以上的 1.x 版本都穩(wěn)定。第二行查動(dòng)態(tài)庫(kù)緩存如果 grep 結(jié)果為空說(shuō)明系統(tǒng)庫(kù)里沒(méi)有 FreeType 或 libpng。注意 ldconfig -p 只能看到運(yùn)行庫(kù)開(kāi)發(fā)頭文件是否在場(chǎng)要用 find 再確認(rèn)一次find /usr/include -maxdepth 3 -name ft2build.h 2/dev/null find /usr/include -maxdepth 3 -name png.h 2/dev/null有的發(fā)行版會(huì)把開(kāi)發(fā)頭文件單獨(dú)拆包運(yùn)行庫(kù)裝了不代表頭文件就位。兩個(gè) find 都沒(méi)有輸出時(shí)apt 系就裝 libfreetype-dev 和 libpng-dev裝完再跑一遍 find看到路徑再往下走。離線環(huán)境也一樣只是換成在聯(lián)網(wǎng)機(jī)器上把對(duì)應(yīng)安裝包下好拷進(jìn)去。3. 編譯安裝 matplotlib 3.7.0解壓、構(gòu)建與離線部署準(zhǔn)備工作就緒后安裝本身很快但快不等于可以盲操作。從解壓源碼包到最終落盤中間涉及版本確認(rèn)、構(gòu)建方式選擇、日志判斷三個(gè)環(huán)節(jié)。這一章按這三步推進(jìn)每一步的參數(shù)含義都交代清楚避免照著抄完也不知道自己在干什么。3.1 解壓源碼包先看目錄結(jié)構(gòu)再確認(rèn)版本元數(shù)據(jù)拿到 matplotlib-3.7.0.tar.gz 后先解壓再進(jìn)目錄tar -zxvf matplotlib-3.7.0.tar.gz cd matplotlib-3.7.0 ls -latar -zxvf 里的 -z 表示 gzip 解壓-x 解包-v 打印過(guò)程-f 指定文件。解壓出來(lái)的根目錄名應(yīng)該是 matplotlib-3.7.0如果發(fā)現(xiàn)根目錄名和文件名對(duì)不上后面大概率還有坑。目錄里 setup.py、setup.cfg 是安裝的主控文件lib/matplotlib 下面是純 Python 實(shí)現(xiàn)src 目錄放 C/C 擴(kuò)展源lib/matplotlib/tests 是自帶測(cè)試集后續(xù)驗(yàn)證環(huán)節(jié)會(huì)用到。進(jìn)入目錄后先做版本確認(rèn)python3 setup.py --version這條命令只讀取元數(shù)據(jù)不觸發(fā)編譯打印出 3.7.0 則說(shuō)明源碼包內(nèi)容與文件名一致。從網(wǎng)上下載的包偶爾會(huì)出現(xiàn)文件名和實(shí)際版本不符的情況花十秒鐘排除掉更穩(wěn)妥。如果這條命令報(bào)錯(cuò)說(shuō)明當(dāng)前解釋器缺少 setuptools順手用 python3 -m pip install setuptools 補(bǔ)上即可。3.2 構(gòu)建安裝pip 模式、--no-deps 與離線 wheelhouse在包目錄里執(zhí)行這條命令python3 -m pip install .注意結(jié)尾的 . 指向當(dāng)前目錄。pip 會(huì)讀取 setup.py 元數(shù)據(jù)解析依賴調(diào)用構(gòu)建后端編譯 C 擴(kuò)展最后寫(xiě)入當(dāng)前解釋器的 site-packages。相比舊式的 python3 setup.py installpip 模式能自動(dòng)處理依賴關(guān)系卸載時(shí)也有記錄不會(huì)在系統(tǒng)里留下一堆孤兒文件。生產(chǎn)環(huán)境里我常用 --no-deps 的方式增強(qiáng)可控性python3 -m pip install . --no-deps python3 -m pip install numpy1.20 kiwisolver cycler pyparsing python-dateutil--no-deps 讓 matplotlib 本體先裝依賴單獨(dú)裝。好處是能精確控制依賴版本壞處是容易漏裝適合團(tuán)隊(duì)里已有固定依賴清單的場(chǎng)景。如果只是自己本地裝直接 pip install . 反而更省心讓 pip 自動(dòng)拉齊依賴即可。離線安裝是另一個(gè)高頻需求。目標(biāo)機(jī)器沒(méi)有外網(wǎng)時(shí)先在聯(lián)網(wǎng)機(jī)器上把依賴全部拉下來(lái)python3 -m pip download . -d /tmp/matplotlib-wheelhouse這條命令會(huì)把 setup.py 里聲明的依賴按當(dāng)前平臺(tái)格式下載到指定目錄包括 matplotlib 本體。然后把整個(gè)目錄拷貝到目標(biāo)機(jī)器執(zhí)行python3 -m pip install --no-index --find-links/tmp/matplotlib-wheelhouse .--no-index 禁止訪問(wèn)遠(yuǎn)程包索引--find-links 指定本地依賴目錄。這套組合拳在離線服務(wù)器上比逐個(gè)下載再手動(dòng)裝省心得多。注意下載依賴時(shí)最好用和目標(biāo)機(jī)器相同系統(tǒng)類型避免平臺(tái)相關(guān)的 wheel 裝不進(jìn)去還要重下。3.3 觀察編譯日志三個(gè)信號(hào)判斷是否成功pip install . 啟動(dòng)后終端會(huì)立刻刷出一大段輸出。新手容易被嚇住其實(shí)只要盯住三個(gè)信號(hào)。第一個(gè)是 Building wheel for matplotlib 或 Running setup.py bdist_wheel for matplotlib看到這行說(shuō)明構(gòu)建流程正常啟動(dòng)。第二個(gè)是編譯進(jìn)度的百分比和 C 編譯器調(diào)用的命令行如果卡在某一行超過(guò)幾分鐘不是機(jī)器慢就是缺東西。第三個(gè)是末尾的 Successfully built matplotlib出現(xiàn)這行才算編譯通過(guò)。編譯耗時(shí)通常在一兩分鐘到十分鐘之間取決于處理器核數(shù)和磁盤速度。numpy 頭文件探測(cè)和 FreeType 鏈接是兩個(gè)主要耗時(shí)點(diǎn)但都是自動(dòng)化流程不用干預(yù)。如果在編譯中段看到紅色 ERROR 和一堆未定義引用基本就是上一章表里那幾類缺失回頭補(bǔ)依賴即可不必重裝解釋器。有一種情況特別容易誤導(dǎo)setup.py 已經(jīng)跑完但日志里沒(méi)有 Successfully installed而是停在 Finished processing dependencies。后者只代表依賴解析完成不代表本體裝好了??吹竭@種輸出建議直接檢查 pip list 里的 matplotlib 條目或者進(jìn)到最后一部分做導(dǎo)入驗(yàn)證別在日志上糾結(jié)。4. 常見(jiàn)問(wèn)題排查四個(gè)翻車點(diǎn)從現(xiàn)象到解決源碼包安裝最耗時(shí)間的環(huán)節(jié)其實(shí)在排錯(cuò)。下面四個(gè)問(wèn)題是我實(shí)際踩過(guò)坑、也幫別人處理過(guò)的按現(xiàn)象、原因、解決三段記錄可以直接對(duì)照。4.1 編譯報(bào)錯(cuò) numpy/arrayobject.h 找不到現(xiàn)象執(zhí)行 pip install . 后日志在 building matplotlib._path extension 附近中斷最后一行是 numpy/arrayobject.h: No such file or directory。原因當(dāng)前解釋器環(huán)境里沒(méi)有 numpy或者 numpy 版本太舊。setup.py 編譯 C 擴(kuò)展時(shí)需要 numpy 的 C API 頭文件并由 numpy.get_include() 提供搜索路徑numpy 不存在時(shí)這個(gè)探測(cè)直接失敗。解決先裝 numpy再裝本體python3 -m pip install numpy1.20 python3 -m pip install .版本下限以官方說(shuō)明為準(zhǔn)但我建議固定到 1.x 系列的較新版本。numpy 2.x 在接口上做過(guò)一輪清理一些按 1.x 寫(xiě)的擴(kuò)展源碼在編譯階段可能報(bào) API 變更類的錯(cuò)誤。裝完后用 python3 -c import numpy; print(numpy.get_include()) 確認(rèn)輸出的是一個(gè)存在的絕對(duì)路徑編譯就會(huì)自動(dòng)找到頭文件。4.2 編譯報(bào)錯(cuò) ft2build.h 或 png.h 找不到現(xiàn)象編譯輸出里出現(xiàn) freetype/fterrors.h: No such file or directory 或 png.h: No such file or directory位置同樣在 C 擴(kuò)展構(gòu)建階段日志還會(huì)附帶 gcc 命令執(zhí)行失敗這類行。原因FreeType 和 libpng 是字體渲染和 PNG 輸出要鏈接的系統(tǒng)庫(kù)。只裝了運(yùn)行庫(kù)沒(méi)裝開(kāi)發(fā)包時(shí)鏈接器能找到動(dòng)態(tài)庫(kù)但編譯器找不到頭文件。發(fā)行版通常把兩者拆成獨(dú)立包這是最常見(jiàn)的遺漏。解決安裝開(kāi)發(fā)包后清理編譯緩存再裝apt-get install -y libfreetype-dev libpng-dev rm -rf build python3 -m pip install .rm -rf build 是很多排錯(cuò)案例里被忽略的步驟。第一次編譯失敗后build 目錄里殘留了舊的探測(cè)結(jié)果即使補(bǔ)上了頭文件構(gòu)建工具仍可能沿用舊配置。清掉重建避免反復(fù)踩同一個(gè)坑。手動(dòng)確認(rèn)頭文件位置find /usr/include -name ft2build.h 2/dev/null find /usr/include -name png.h 2/dev/null兩個(gè) find 都有輸出后再跑安裝命令基本一次過(guò)。4.3 導(dǎo)入時(shí)報(bào) ModuleNotFoundError: No module named tkinter現(xiàn)象安裝成功但執(zhí)行 import matplotlib.pyplot as plt 拋 ModuleNotFoundError: No module named tkinter。原因pyplot 在初始化交互后端時(shí)會(huì)嘗試導(dǎo)入 Tkinter。當(dāng)前解釋器在編譯時(shí)沒(méi)有啟用 tkinter 模塊或系統(tǒng)缺少 tk 相關(guān)庫(kù)。這個(gè)情況在容器環(huán)境里尤其常見(jiàn)基礎(chǔ)鏡像一般不攜帶圖形相關(guān)組件。解決二選一。需要交互窗口時(shí)裝對(duì)應(yīng)的 tk 包apt-get install -y python3-tk版本要與解釋器對(duì)應(yīng)例如 Python 3.11 對(duì)應(yīng) python3.11-tk。如果根本不需要 GUI直接在代碼或環(huán)境變量里指定 Agg 后端export MPLBACKENDAgg python3 your_script.pyMPLBACKEND 是 matplotlib 讀取的運(yùn)行時(shí)后端環(huán)境變量寫(xiě)成 Agg 后所有繪圖操作都不會(huì)碰 Tkinter。這個(gè)方案對(duì)守護(hù)進(jìn)程、定時(shí)任務(wù)類腳本特別實(shí)用既繞開(kāi)依賴又避免彈窗阻塞。4.4 同機(jī)多 Python 裝錯(cuò)環(huán)境裝完卻 import 不到現(xiàn)象安裝命令顯示 Successfully installed matplotlib-3.7.0但寫(xiě)腳本運(yùn)行時(shí) ModuleNotFoundError: No module named matplotlib或者打印出的版本是舊的 3.x。原因安裝用的解釋器和運(yùn)行用的解釋器不是同一個(gè)。典型場(chǎng)景某個(gè)軟件自帶一套解釋器或系統(tǒng)里并存多個(gè)版本PATH 里的 python3 指向 A而 pip 屬于 B。解決全程用解釋器的絕對(duì)路徑綁定操作/opt/python3.11/bin/python3 -m pip install . /opt/python3.11/bin/python3 -c import matplotlib; print(matplotlib.__version__)第一行把包裝進(jìn)絕對(duì)路徑對(duì)應(yīng)的解釋器第二行驗(yàn)證同一個(gè)解釋器能導(dǎo)入兩步之間不依賴 PATH。裝錯(cuò)環(huán)境不需要卸載在目標(biāo)解釋器里重新裝一次即可site-packages 目錄彼此隔離。從此我不用裸 pip所有安裝一律 python3 -m pip這一條就能擋掉大半裝完找不到的玄學(xué)問(wèn)題。5. 裝完怎么驗(yàn)證三層檢查把繪圖鏈路跑通安裝完成的信號(hào)不是 Successfully installed而是新開(kāi)終端后依然能正常導(dǎo)入、正常出圖。我把驗(yàn)證拆成三層每層都很短但各自覆蓋一段鏈路第一層驗(yàn)證包本身第二層驗(yàn)證后端選擇第三層驗(yàn)證從數(shù)據(jù)到 PNG 文件的完整管線。5.1 版本與安裝路徑核對(duì)python3 -c import matplotlib; print(matplotlib.__version__); print(matplotlib.__file__)這行命令應(yīng)該在當(dāng)前解釋器里輸出 3.7.0 和一個(gè) site-packages 下面的路徑。路徑就是剛才 pip install 時(shí)使用的解釋器目錄如果和預(yù)期不符回到 4.4 節(jié)檢查解釋器配對(duì)。這一步能立刻暴露安裝到錯(cuò)誤環(huán)境的問(wèn)題。5.2 后端確認(rèn)TkAgg、QtAgg 與 Agg 的區(qū)別python3 -c import matplotlib; print(matplotlib.get_backend())有桌面的機(jī)器通常輸出 TkAgg 或 QtAgg無(wú)頭服務(wù)器輸出 Agg。看到 Agg 不需要緊張后端只是決定繪圖結(jié)果如何呈現(xiàn)Agg 直接把圖形渲染到內(nèi)存再保存成文件不彈任何窗口。對(duì)后臺(tái)任務(wù)來(lái)說(shuō) Agg 反而是最干凈的選擇。5.3 繪圖落盤測(cè)試從數(shù)據(jù)到 PNG 的完整鏈路python3 -c from matplotlib import pyplot as plt; plt.plot([1, 2, 3], [4, 2, 6]); plt.savefig(/tmp/matplotlib-check.png)接著用 file 命令確認(rèn)產(chǎn)物格式file /tmp/matplotlib-check.png輸出里應(yīng)有 PNG image data 之類的描述說(shuō)明字體、渲染、編碼這條鏈路全部正常。如果 savefig 報(bào)錯(cuò)優(yōu)先看字體警告——很多情況下是系統(tǒng)缺字體目錄而不是 matplotlib 本身的問(wèn)題去配置里指定一個(gè)存在的字體路徑即可。從那以后我每次在新環(huán)境裝完 matplotlib不管是通過(guò) pip 直接裝的 wheel還是這次這樣的源碼包都會(huì)強(qiáng)制把這三層驗(yàn)證跑一遍不停留在安裝成功那一步。源碼安裝最大的特點(diǎn)是解釋器路徑、系統(tǒng)庫(kù)、依賴版本缺一不可任何一個(gè)環(huán)節(jié)有偏差都可能讓前面幾十分鐘的編譯白費(fèi)。希望這份記錄能幫你把這套流程一次走通少踩幾個(gè)我當(dāng)年踩過(guò)的坑。本文還有配套的精品資源點(diǎn)擊獲取