Poetry vs pip

Poetry 與 pip 一樣可以用於套件管理,但多了以下功能:

  • 虛擬環境管理:使用內建的 venv 或 virtualenv 套件來建立及管理 Python 的虛擬環境,不同虛擬環境間彼此獨立
  • 套件相依性管理:管理環境中所安裝的全部套件及其版本。若一個套件被兩個以上的套件依賴 (dependency),而彼此要求的版本範圍沒有交集,則套件可能會失效或無法安裝。
  • 套件的打包與發布

pip 的缺點:

  • 沒有完整套件相依性管理功能,難以乾淨地移除套件。
  • 若一個套件有多個依賴套件,在使用 pip uninstall 時無法找出這些依賴套件並移除。若強行移除依賴套件可能會導致另一個依賴它的套件失效。

安裝 Poetry

Poetry 主要有兩種安裝方式,官方推薦使用全域安裝。

  • Linux, macOS, Windows (WSL)

    curl -sSL https://install.python-poetry.org | python3 -
  • Windows (Powershell)

    (Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | py -

Poetry 安裝路徑

  • Unix 系統:$HOME/.local/bin
  • Windows 系統:%APPDATA%\Python\Scripts

將此路徑加入環境變數即可在終端機直接使用 poetry 指令。

初始化 Poetry 專案設定

每一個使用 Poetry 的專案都需要一個 pyproject.toml 設定檔,因此進入新的專案要先初始化。

首先進入專案資料夾並輸入 poetry init

cd <project folder>
poetry init

接著會進入互動式的介面,前五項可以直接 enter 確認,第六項 Compatible Python versions 請確認是否符合你要的 Python 版本,若要更改請輸入 ^3.x

最後兩項先輸入 no 跳過,接著會讓你確認即將產生的內容,最後再按 enter 確認即可:

This command will guide you through creating your pyproject.toml config.

Package name [reminder-bot]:
Version [0.1.0]:  
Description []:  
Author [Your Name <you@example.com>, n to skip]:  
License []:  
Compatible Python versions [^3.9]:

Would you like to define your main dependencies interactively? (yes/no) [yes] no
Would you like to define your development dependencies interactively? (yes/no) [yes] no
Generated file

[tool.poetry]
name = "reminder-bot"
version = "0.1.0"
description = ""
authors = ["JHTNT <jerry1106666@gmail.com>"]
readme = "README.md"
packages = [{include = "reminder_bot"}]

[tool.poetry.dependencies]
python = "^3.9"


[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

可以看到目錄裡多了 pyproject.toml 就表示初始化完成了。

管理 Poetry 虛擬環境

Poetry 整合了 virtualenv,預設強制將套件安裝在虛擬環境,若輸入指令時不在虛擬環境中會自動建立一個新的虛擬環境

但是 Poetry 預設將虛擬環境放在同一個資料夾集中管理,個人更偏好 venv 建立在專案目錄內的方式,因此需要修改 Poetry 的設定。

修改 Poetry config

輸入 poetry config --list 來查看有哪些指令,我們要修改的是 virtualenvs.in-project = null 這一項

使用以下指令來修改設定:

poetry config virtualenvs.in-project true

若之前建立過虛擬環境先刪除:

poetry env remove python

接著建立新的虛擬環境(若電腦只有一個 Python 版本):

poetry env use python

建立新的虛擬環境(使用 pyenv 管理)

poetry env use $(pyenv which python)

關於使用 pyenv 管理 Python 版本可以參考使用 pyenv 管理 Python 版本

啟動與退出虛擬環境

輸入 poetry shell 啟動虛擬環境,再輸入 exit 可以退出。

Poetry 指令

新增套件

相當於 pip install,會詳細列出安裝了哪些套件。

poetry add <package name>

可以發現 pyproject.tomltool.poetry.dependencies 區域多了剛剛新增的套件及版本,且只有我們主動新增的套件。

新增開發環境套件

在開發專案時可能會用到一些測試或檢查的工具,但在部署時是不需要的,此時可以加上 --dev-D 參數,將工具與必要的套件區分。

poetry add <package name> --group dev
poetry add <package name> -G dev

目前 poetry 已棄用 --dev, -D 的參數,改為使用 --group dev / -G dev

這樣新增的套件會出現在 tool.poetry.dev-dependencies 區域。

poetry.lock 的更新

執行上述的 poetry add 以及稍後會介紹的 poetry remove 時可以發現,除了 pyproject.toml 以外還有另一個叫 poetry.lock 的檔案內容會變動。這個檔案相當於 pip 的 requirements.txt,記錄了所有安裝的套件與版本。

當你執行 poetry add 時,Poetry 實際上做了三件事:

  1. 更新 pyproject.toml
  2. 解析 pyproject.toml 的套件版本後,更新 poetry.lock
  3. 根據 poetry.lock 的內容更新專案的套件

由於 pyproject.tomlpoetry.lock 不會自動同步,若手動編輯 pyproject.toml 後需要更新 poetry.lock 的內容,可以使用 poetry lock 指令,但直接執行的話會「順便」將依賴套件更新到最新版,這可能會導致某些問題,因此可以加上 --no-update 參數來避免此行為:

poetry lock --no-update

更新完 poetry.lock 之後還不會更新套件,需要再執行此指令:

poetry install

更新套件

指令很直覺,就是 update,這樣會一次更新專案中所有可更新的套件:

poetry update

若只想要更新特定幾個套件,可以在後面指定套件名稱:

poetry update <package 1> [<package 2> ...]

需要注意的是可以更新的版本會受到 pyproject.toml 的限制,例如 black = "^23.3.0"。比較常用的是語意化版本的方式,可以查看語意化版本 (Semantic Versioning) 是什麼(未寫),其他詳細的方法參考 Poetry 的官方文件 Dependency specification

列出套件清單

指令為 poetry show,等同於 pip list。注意套件清單的來源是 poetry.lock 而不是虛擬環境。

poetry show

若要使用樹狀顯示可以加上 --tree 參數,可以很直觀的看出主要套件與其依賴套件的關係:

poetry show --tree

還可以只顯示指定套件的依賴清單:

poetry show <package name> --tree

移除套件

使用方法就跟 poetry add 一樣,加上 --dev-D 可以移除開發用的套件。

這也是與 pip 最大的不同,Poetry 具有相依性管理的能力,可以確認要移除的套件有哪些依賴套件,並確保這些依賴套件不被其他套件使用才移除。

輸出 requirements.txt

有時候在某些環境還是會有使用 requirements.txt 的需求,此時可以用 poetry export 來導出套件,雖然看起來跟平常熟知的 requirements.txt 不一樣,但還是能正常使用。

poetry export -o requirements.txt

Reference