大概在 2 年前就聽過 Poetry 的大名,不過那時我還沒有套件相依性管理的強烈需求,加上看起來需要一些學習成本(確實如此),所以就一直擱在一旁,直到真正體會到了 pip 的不足。
pip 是 Python 內建的套件管理工具,而它的最大罩門,就是對於「套件間的相依性管理」能力不足。尤其是在「移除」套件時的依賴解析——可以說沒有。這也是我提議改用 Poetry 的根本原因。
怎麼說?看完下面的例子就能明白。
pip uninstall
的困境:以 Flask 為例假設現在你的工作專案中有開發 API 的需求,經過一番研究與討論,決定使用 Flask 網頁框架來進行開發。
我們知道,很多套件都有依賴的套件,也就是使用「別人已經造好的輪子」來構成套件功能的一部分。
安裝主套件時,這些依賴套件也必須一併安裝,主套件才能正常運作,這裡的 Flask 就是如此。安裝 Flask 時,不會只安裝單一個flask
套件,還會安裝所有 Flask 的必要構成部分——也就是依賴套件,結果如下:
❯ pip install flask
Collecting flask
Downloading Flask-2.1.1-py3-none-any.whl (95 kB)
|████████████████████████████████| 95 kB 993 kB/s
...
Installing collected packages: zipp, MarkupSafe, Werkzeug, Jinja2, itsdangerous, importlib-metadata, click, flask
Successfully installed Jinja2-3.1.1 MarkupSafe-2.1.1 Werkzeug-2.1.1 click-8.1.2 flask-2.1.1 importlib-metadata-4.11.3 itsdangerous-2.1.2 zipp-3.7.0
從上可知,pip install flask
還會一併安裝importlib-metadata
、itsdangerous
等 7 個依賴套件,實際上總共安裝了 8 個套件!
可以說,pip 在「安裝」套件時的相依性管理還是可以的,這並不難,因為套件的依賴要求都寫在安裝檔裡了,根本不需要「管理」。
附帶一提,這 8 個套件包括flask
,除了importlib-metadata
和zipp
外,其餘 6 個實際上都是由 Flask 團隊自行開發。
但並非只有 Flask 框架會使用(依賴)這些套件。
比如其中的 Click 就是一個被廣泛使用的命令列製作工具。套件官網是這麼介紹的:
Click is a Python package for creating beautiful command line interfaces in a composable way with as little code as necessary.
別的套件也可能依賴click
來提供命令列的功能,換句話說,主套件的依賴套件也可能被其他第三方套件所依賴、使用。這就產生了「衝突」的可能。
好,一切都很美好,就這樣一年過去,團隊決定改用火紅的 FastAPI 取代 Flask 來實作專案的 API,作為 API 的主要開發人員,你對新技術充滿了期待(或排斥),興高采列地安裝了 FastAPI,更新了所有程式碼,最後要移除 Flask,這時問題就來了。
安裝 Flask 的時候,我們只需要pip install flask
,pip 就會幫你一併安裝所有依賴套件。現在要移除它,也只要pip uninstall flask
就可以了嗎?
很遺憾,答案是否定的。