poetry 入門完全指南

視頻地址:BV1S14y1Q7pP
使用 poetry 作為項(xiàng)目的虛擬環(huán)境已經(jīng)蠻久了,這個(gè)工具雖然非常好用,但是一致沒有用于生成環(huán)境之中,也沒有力薦這個(gè)工具的使用。 如果感覺差不多是時(shí)候了,所以打算把虛擬環(huán)境改為?poetry
,不在使用其他的虛擬環(huán)境。
相比 pip 與 venv 的使用,poetry 確實(shí)有一定的學(xué)習(xí)門檻,需要先理清楚 pip 與 虛擬環(huán)境之間的關(guān)系,然后才能學(xué)習(xí) poetry 的使用。 現(xiàn)在我把自己的項(xiàng)目全部用 poetry 來進(jìn)行管理,使用體驗(yàn)遠(yuǎn)遠(yuǎn)大于我之前用過的?pip + venv
、pyenv
、conda
?的虛擬環(huán)境。
poetry 是什么
https://python-poetry.org/
Poetry 差不多是 pip + venv,的結(jié)合體??梢灶愃?pip 用于管理第三方模塊的管理,但是比 pip 的功能強(qiáng)大許多,同時(shí)還包含 venv 的虛擬環(huán)境管理功能。大致的功能如下:
管理第三方模塊的安裝與卸載
管理虛擬環(huán)境
管理虛擬環(huán)境的依賴
管理打包與發(fā)布 其中最重要的是?
虛擬環(huán)境的依賴
,意識(shí)本文的重點(diǎn)。至于?打包與發(fā)布
?對(duì)于開發(fā)者用的不是很多,在這里就不介紹了。
名詞解釋:虛擬環(huán)境管理、模塊管理、模塊依賴管理
在開始之前,先介紹一下它們之間的關(guān)系。
虛擬環(huán)境
虛擬環(huán)境是指內(nèi)建的 venv 或 virtualenv 、 conda 以及其他用來創(chuàng)建與管理 Python 虛擬環(huán)境的工具,不同的虛擬環(huán)境各自獨(dú)立,存放的位置、安裝的模塊也都不一樣。
模塊管理、模塊依賴管理
模塊是指虛擬環(huán)境中安裝的第三方模塊及其版本。大多數(shù)項(xiàng)目對(duì)第三方庫的版本都是有特定要求,如果對(duì)舊版本的項(xiàng)目使用新版本的依賴,可能會(huì)報(bào)很奇怪的錯(cuò)誤。
當(dāng)安裝第三方模塊時(shí),第三方模塊可能會(huì)安裝自己依賴的模塊。當(dāng)安裝兩個(gè)以上模塊時(shí),就可能出現(xiàn)第三方模塊的依賴出現(xiàn)沖突。這種情況一般是依賴的版本沖突。這種就叫做相關(guān)性依賴
pip 的不足
大概在三年前就聽說過 poetry 的大名,不過那時(shí)候 venv 能滿足我的需求,并且對(duì)虛擬環(huán)境及其依賴管理了解不多, poetry 官方文檔是英文的也不怎么看的懂, 學(xué)習(xí)起來有一定的成本,所以就擱置了。知道真正的體會(huì)到了 pip + venv 的不足。
pip 是 python 內(nèi)置的依賴管理工具,而它最大的不足在于?第三方模塊的相關(guān)性依賴管理
?的能力不足。尤其是在刪除第三方模塊是的依賴解析, 可以說是不會(huì)分析依賴。這也是我選擇 poetry 的一個(gè)重要原因。
接下來我們看一個(gè)案例:
1、創(chuàng)建虛擬環(huán)境
2、安裝 flask 并查看安裝好的第三方模塊(依賴)
3、然后刪除 flask 模塊
然后就會(huì)發(fā)現(xiàn),只少了 flask 模塊,而安裝 flask 時(shí)順帶安裝的依賴全部被留下了。也就是說 pip 安裝模塊是,相關(guān)的依賴都會(huì)被下載安裝。但是在刪除是,pip 就不會(huì)進(jìn)行管理了,而是直接把指定的模塊移除,留下一堆依賴。
從零開始使用 Poetry
安裝
poetry 是一個(gè)命令行工具,安裝之后就可以使用 poetry 指令??梢詫⑵浒惭b全局環(huán)境或者是虛擬環(huán)境,我推薦安裝在全局環(huán)境,這樣在后面使用時(shí)不需要單獨(dú)激活虛擬環(huán)境。同時(shí) poetry 也依賴了比較多的模塊,每個(gè)虛擬環(huán)境都安裝一次也會(huì)比較麻煩。
安裝之后就會(huì)在 python 解釋器的安裝目錄下的?Scripts
?目錄里面出現(xiàn)?poetry.exe
,因?yàn)樵诎惭b python 解釋器是配置過環(huán)境變量,然后就可以直接全局使用了。
初始化 poetry 項(xiàng)目
為了方便解說,我們先創(chuàng)建一個(gè)新的項(xiàng)目,名稱為?poetry-demo
指定都非常簡單,建議跟著一步步自己也嘗試一下。
1、初始化項(xiàng)目
然后會(huì)跳出來一連串的互動(dòng)對(duì)話,用于創(chuàng)建項(xiàng)目的配置文件,這里我就直接全部一路回車,然后看一下生成的?pyproject.toml
?配置文件:
此時(shí)項(xiàng)目的目錄接口如下:
管理虛擬環(huán)境
poetry 預(yù)設(shè)了很多自己的虛擬環(huán)境配置,這些配置可以通過?poetry config
?進(jìn)行修改。
Windows 系統(tǒng)下 poetry 預(yù)設(shè)是將虛擬環(huán)境創(chuàng)建在?C:\Users\<用戶名>\AppData\Local\pypoetry\Cache\virtualenvs
?目錄下,當(dāng)用戶在執(zhí)行?poetry add
?等指令時(shí),poetry 都會(huì)自動(dòng)檢查當(dāng)下是否正在使用虛擬環(huán)境:
如果是,則會(huì)直接安裝模塊到當(dāng)前的虛擬環(huán)境下
如果否,則會(huì)自動(dòng)幫你創(chuàng)建一個(gè)新的虛擬環(huán)境,然后再安裝模塊
注意:如果之前使用過 venv 、 virtualenv 或者其他的虛擬環(huán)境,poetry 默認(rèn)的虛擬環(huán)境跟他們的有一點(diǎn)不一樣,不過后面可以通過 poetry config 修改配置解決這個(gè)問題。
創(chuàng)建虛擬環(huán)境
使用指令?poetry env use python
:
可以看出 poetry 為創(chuàng)建創(chuàng)建一個(gè)名為?poetry-demo-Ut74gzEx-py3.10
?的虛擬環(huán)境
重點(diǎn)說明
poetry env use python
?是使用當(dāng)前命令行下激活的 python 解釋器創(chuàng)建虛擬環(huán)境也可以將指令最后的?
python
?,改為?python3
、python3.8
,之類的,甚至只要需要?3.8
,只要確保對(duì)于的解釋器能夠在環(huán)境變量中找到。更多的配置可以查看?官方文檔
poetry 默認(rèn)會(huì)將虛擬環(huán)境統(tǒng)一放在指定目錄,例如剛剛創(chuàng)建的項(xiàng)目就放在?
C:\Users\xxp\AppData\Local\pypoetry\Cache\virtualenvs\
?目錄當(dāng)中虛擬環(huán)境的命名模式為?
項(xiàng)目名-隨機(jī)數(shù)-python版本
對(duì)于這種命名我個(gè)人是蠻喜歡的,每個(gè)項(xiàng)目有一個(gè)單獨(dú)虛擬環(huán)境,并且制定了對(duì)應(yīng)的版本,看一眼就能知道自己使用的環(huán)境是否正確。
對(duì)于 poetry 將虛擬環(huán)境統(tǒng)一放在指定路徑下,這一點(diǎn)我更偏向于?venv
?的做法,也就是把虛擬環(huán)境放在項(xiàng)目目錄下,方便用于觀看依賴包的源碼,在做項(xiàng)目部署的時(shí)候更方便一些。
所幸 poetry 提供了這樣的選項(xiàng)。
在當(dāng)前項(xiàng)目下創(chuàng)建虛擬環(huán)境
我們可以使用?poetry config --list
?指令來查看 poetry 的幾個(gè)主要設(shè)定,
其中?virtualenvs.create = true
?若改為?false
,則可以停止 poetry 在檢查不到虛擬環(huán)境是自動(dòng)創(chuàng)建的行為模式,但是建議不要改動(dòng)。
而?virtualenvs.in-project = false
?就是我們要修改的目標(biāo),使用指令:
先把之前創(chuàng)建的虛擬環(huán)境刪除
重新創(chuàng)建虛擬環(huán)境,看一下差異:
可以看出:
虛擬環(huán)境的路徑改為項(xiàng)目的根目錄下了
名稱固定位?
.venv
個(gè)人覺得這樣的設(shè)定更加簡潔。
啟動(dòng)與退出虛擬環(huán)境
在項(xiàng)目的根目錄下使用?poetry shell
?就可以進(jìn)入到虛擬環(huán)境
poetry shell 指令會(huì)檢查當(dāng)前目錄或上層目錄是否存在?pyproject,toml
?來確定需要啟動(dòng)的虛擬環(huán)境,所以如果不移動(dòng)到項(xiàng)目的目錄下,則會(huì)出現(xiàn)錯(cuò)誤。
退出虛擬環(huán)境就更簡單了,只要輸入?exit
?就可以了。
poetry 指令
poetry 是一個(gè)獨(dú)立的命令行工具,他有自己的指令,需要花費(fèi)額外的時(shí)間與精力學(xué)習(xí),相較 pip 更加復(fù)雜,這個(gè)能是使用 poetry 的一道關(guān)卡。好在常用指令其實(shí)不超過 10 個(gè),下面就來一一介紹。
安裝模塊
使用指令
相較于?pip install
,我們?cè)囋嚢惭b flask 看看會(huì)有什么樣的變化
可以看到 poetry 會(huì)將所有的信息全部列出來,并且清楚的告知了新增了那些第三方模塊。
此時(shí)項(xiàng)目中的?pyproject.toml
?也發(fā)生了變化
這里要說明,安裝 flask ,則?pyproject.toml
?只會(huì)新增?flask = "^2.3.2"
?這個(gè)字段的第三方模塊,其余依賴不會(huì)出現(xiàn)在?toml
?文件中。
這里是一個(gè)非常大的優(yōu)點(diǎn),以便區(qū)分那些是用戶安裝的第三方模塊,那些是第三方模塊一并安裝的依賴。
poetry.lock
?與更新順序
除了更新?pyproject.toml
?,此時(shí)項(xiàng)目中還會(huì)新增一個(gè)文件,名為?poetry.lock
?,它實(shí)際上就相當(dāng)于?pip
?的?requirements.txt
?,詳細(xì)記錄了所有安裝的模塊與版本。
當(dāng)使用?poetry add
?指令時(shí),poetry
?會(huì)自動(dòng)依序幫你做完這三件事:
更新?
pyproject.toml
。依照?
pyproject.toml
?的內(nèi)容,更新?poetry.lock
?。依照?
poetry.lock
?的內(nèi)容,更新虛擬環(huán)境。
由此可見,?poetry.lock
?的內(nèi)容是取決于?pyproject.toml
?,但兩者并不會(huì)自己連動(dòng),一定要基于特定指令才會(huì)進(jìn)行同步與更新,?poetry add
?就是一個(gè)典型案例。
此時(shí)項(xiàng)目目錄結(jié)構(gòu)如下:
poetry lock :更新 poetry.lock
當(dāng)你自行修改了?pyproject.toml
?內(nèi)容,比如變更特定模塊的版本(這是有可能的,尤其在手動(dòng)處理版本沖突的時(shí)候),此時(shí)?poetry.lock
?的內(nèi)容與?pyproject.toml
?出現(xiàn)了脫鉤,必須讓它依照新的?pyproject.toml
?內(nèi)容更新、同步,使用指令:
如此一來,才能確保手動(dòng)修改的內(nèi)容,也更新到?poetry.lock
?中,畢竟虛擬環(huán)境如果要重新建立,是基于?poetry.lock
?的內(nèi)容來安裝模塊,而非?pyproject.toml
?。
還是那句話:
poetry.lock 相當(dāng)于 Poetry 的 requirements.txt 。
但要特別注意的是,?poetry lock
?指令,僅會(huì)更新?poetry.lock
?,不會(huì)同時(shí)安裝模塊至虛擬環(huán)境
因此,在執(zhí)行完?poetry lock
?指令后,必須再使用?poetry install
?來安裝模塊。否則就會(huì)出現(xiàn)?poetry.lock
?和虛擬環(huán)境不一致的狀況。
更多?poetry lock
?細(xì)節(jié)可參考 官方文件,其中特別值得注意的是?--no-update
?參數(shù)。
新增模塊至 dev-dependencies
有些模塊,比如?pytest
?、?black
?等等,只會(huì)在開發(fā)環(huán)境中使用,產(chǎn)品的部署環(huán)境并不需要。
Poetry 允許你區(qū)分這兩者,將上述的模塊安裝至?dev-dependencies
?區(qū)塊,方便讓你輕松建立一份「不包含」?dev-dependencies
?開發(fā)模塊的安裝清單。
在此以 Black 為例,安裝方式如下:
結(jié)果的區(qū)別顯示在?pyproject.toml
?里:
可以看到?black
?被列在不同區(qū)塊:?tool.poetry.dev-dependencies
?。
強(qiáng)烈建議善用 dev-dependencies
善用?--group dev
?參數(shù),明確區(qū)分開發(fā)環(huán)境,我認(rèn)為非常必要。
首先,這些模塊常常屬于「檢測型」工具,相關(guān)的依賴模塊著實(shí)不少!比如?flake8
?,它依賴了?pycodestyle
?、?pyflakes
?、?mccabe
?等等,還有?black
?、?pre-commit
?,依賴模塊數(shù)量也都很可觀。
Poetry 更新模塊
這個(gè)就很簡單了,使用?poetry update
?指令即可:
上面指令會(huì)更新全部可能可以更新的模塊,也可以僅指定特定模塊,比如:
關(guān)于?poetry update
?的其余參數(shù),請(qǐng)參考文件。
還一件重要的事,那就是關(guān)于模塊版本的升級(jí)限制規(guī)則,取決于你在?pyproject.toml
?中的設(shè)定。
列出全部模塊清單
類似?pip list
?,這里要使用?poetry show
特別提醒的是,這里的清單內(nèi)容并不是來自于虛擬環(huán)境,這點(diǎn)和 pip 不同,而是來自于?poetry.lock
?的內(nèi)容。
你可能會(huì)想,來自于?poetry.lock
?或虛擬環(huán)境,有差嗎?兩者不是應(yīng)該要一致?
沒錯(cuò),理論上是,但也有不一致的時(shí)候,比如你使用了?pip install
?指令安裝模塊,就不會(huì)記載在?poetry.lock
?中,那?poetry show
?自然也不會(huì)顯示。
樹狀顯示模塊依賴層級(jí)
讓主要模塊與其依賴模塊的關(guān)系與層次,一目了然。
而且很貼心的是,它也可以只顯示指定模塊的依賴層級(jí),以?celery
?為例:
Poetry 移除模塊
使用?poetry remove
?指令。和?poetry add
?一樣,可以加上?-D
?參數(shù)來移除置于開發(fā)區(qū)的模塊。
而移除模塊時(shí)的依賴解析能力,正是 Poetry 遠(yuǎn)優(yōu)于 pip 的主要環(huán)節(jié),因?yàn)?pip 沒有嘛!也是我提議改用 Poetry 的關(guān)鍵理由——為了順利移除模塊與依賴。
前面已經(jīng)提過,pip 的?pip uninstall
?只會(huì)移除你所指定的模塊,而不會(huì)連同依賴模塊一起移除。
這是基于安全考量,因?yàn)?pip 沒有依賴解析功能。如果貿(mào)然移除所有安裝時(shí)一并安裝的依賴模塊,可能會(huì)造成巨大災(zāi)難,讓別的模塊失去效用。
所以,使用 pip 時(shí),我們鮮少會(huì)去移除已經(jīng)不再使用的模塊。畢竟依賴關(guān)系錯(cuò)綜復(fù)雜,移除模塊可能造成許多副作用,實(shí)在是太麻煩了。
poetry remove 的依賴解析
輸出 Poetry 虛擬環(huán)境的 requirements.txt
理論上,全面改用 Poetry 后,項(xiàng)目中是不需要存在?requirements.txt
?,因?yàn)樗慕巧呀?jīng)完全被?poetry.lock
?所取代。
但事實(shí)是,你可能還是需要它,甚至希望它隨著?poetry.lock
?的內(nèi)容更新!至少對(duì)我而言就是如此,我在 Docker 部署環(huán)境中并不使用 Poetry,所以我需要一份完全等價(jià)于?poetry.lock
?的?requirements.txt
?,用于 Docker 部署。
你可能想說,那我就在 Poetry 的虛擬環(huán)境下,使用以往熟悉的指令?pip freeze > requirements.txt
?來產(chǎn)生一份就可以了吧?我本來也是這么想,但實(shí)際的產(chǎn)出卻是如此:(提醒:目前 poetry-demo 專案中僅剩下 Black 和它的依賴模塊)
這呈現(xiàn)好像不是我們以前熟悉的那樣:
沒錯(cuò),只要是使用?poetry add
?安裝的模塊,在?pip freeze
?就會(huì)變成這樣。此時(shí)想輸出類似?requirements.txt
?的格式,需要使用?poetry export
?。
我們?cè)倏匆幌螺敵鼋Y(jié)果,雖然不盡相同,但也相去不遠(yuǎn)了……嗎?等等,怎么是空白?
輸出 dev-dependencies 輸出 dev-dependencies
因?yàn)?poetry export
?預(yù)設(shè)只會(huì)輸出?toml
?中的?[tool.poetry.dependencies]
?區(qū)塊的模塊!還記得上面我們把 Black 安裝到?[tool.poetry.dev-dependencies]
?了嗎?
這倒是沒錯(cuò),不過基于演示需求,我們必須輸出?[tool.poetry.dev-dependencies]
?的模塊,才能看到 Black。
加上?--dev
?參數(shù)即可:
輸出的?requirements.txt
?內(nèi)容:
雖然長得有點(diǎn)不一樣,但這個(gè)檔案確實(shí)是可以?pip install
?的。
從這里也可以看出先前一再提及區(qū)分開發(fā)、部署依賴的價(jià)值——大部分時(shí)候我們并不需要輸出開發(fā)用模塊。
poetry export
?所有參數(shù)用法與說明,請(qǐng)參考 官方文件。
Poetry 常用指令清單
算來算去,Poetry 的常用指令主要有下面幾個(gè):
poetry add
poetry remove
poetry export
poetry env use
poetry shell
poetry show
poetry init
poetry install
其中一半,單一項(xiàng)目可能只會(huì)用個(gè)一兩次而已,比如?init
?、?install
?和?env use
?,實(shí)際上需要學(xué)習(xí)的指令并不多。
那么,只要知曉這些指令,就可以順利運(yùn)用 Poetry 了嗎?可能是,也可能否,所以我下面還會(huì)再補(bǔ)充 Poetry 的常見使用情境與操作方式,讓你接納 Poetry 的阻力可以進(jìn)一步下降!