Python詩歌:現代高效的Python環境和依賴管理

Python 的生態系統傳統上依賴於像 pipvirtualenv 這樣的工具來管理依賴和項目環境。儘管這些工具一直以來都很好用,但它們常常導致依賴衝突、手動環境管理以及團隊間項目設定不一致。

Python Poetry 通過提供一個現代化、統一的依賴和環境管理工具來解決這些挑戰。它涵蓋了從虛擬環境到套件發布的所有內容,同時通過智能依賴解析確保可復現的構建。

本指南將向您展示如何使用Poetry來精簡您的Python開發工作流程,避免常見的依賴問題。

Python Poetry vs. PIP

Poetry和pip在Python生態系統中有不同的用途。儘管 pip 主要是一個包安裝器,Poetry則是一個完整的依賴和項目管理工具。以下是主要區別:

1. 依賴解析

  • Pip:簡單的線性依賴解析,可能導致衝突
  • 詩歌:高級依賴解析器,在安裝前防止衝突

2. 虛擬環境管理

  • Pip:需要單獨的工具(virtualenv、venv)和手動激活
  • Poetry:自動為每個項目創建並管理虛擬環境

3. 項目配置

  • Pip:使用requirements.txt進行依賴,使用setup.py進行項目元數據
  • 詩歌:單一的pyproject.toml文件滿足所有配置需求

4. 鎖定文件

  • Pip:不支援內建的鎖定文件功能
  • Poetry:生成poetry.lock以實現在各種環境中可重現的構建

5. 封裝發布

  • Pip:需要額外的工具(twine、setuptools)來進行發布
  • Poetry:內建命令用於構建和發布封裝

何時該使用Poetry而不是pip

選擇Poetry的時機:

  • 在需要可重複使用環境的團隊項目中工作
  • 構建將發布到PyPI的套件
  • 管理具有潛在衝突的複雜依賴樹
  • 需要自動化虛擬環境管理
  • 希望一個工具覆蓋整個開發工作流程

在以下情況下使用pip:Stick with pip when:

  • 僅需最少依賴的簡單腳本
  • 首次學習Python
  • 需要快速安裝單個套件
  • 在無法安裝Poetry的環境中工作
  • 維護已經使用pip設置的遺留項目

一般準則是:對於任何將共享、部署或長期維護的項目使用Poetry。對於快速實驗或學習練習使用pip。

話雖如此,讓我們立即開始使用Poetry。

設置Python Poetry

您將主要通過命令行(CLI)工具與Poetry互動,因此在您的機器上系統范圍內安裝它是合理的。本部分涵蓋這一關鍵的第一步,以及如何根據您的需求設置Poetry的一些默認配置。

安裝Poetry

您可以使用官方安裝程序腳本來安裝Poetry,該腳本可以通過單個命令下載並運行。

對於macOS、Linux和WSL2:

$ curl -sSL https://install.python-poetry.org | sudo python3 -

對於Windows Powershell(以管理員特權運行):

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

如果您使用的是Windows,并且已經從Microsoft Store安裝了Python(出於某種奇怪的原因),那麼請在上面的命令中將 py 替換為 python

安裝腳本完成後,會顯示一條消息,要求您將 Poetry 添加到您的 PATH 中,以便 poetry 命令在任何地方都可用。

對於 macOS、Linux 和 WSL2,請將以下行添加到您的 shell 腳本中,比如 .bashrc.zshrc

$ export PATH="/Users/bexgboost/.local/bin:$PATH"

對於Windows,您可以按照輸出指示進行操作。

之後,運行以下命令驗證您的安裝poetry --version

配置 Poetry

Poetry 的大部分配置是關於如何創建虛擬環境和安裝軟件包的。您可以使用以下命令列印(幾乎)所有 Poetry 配置:

$ poetry config --list

輸出將類似於以下內容:

cache-dir = "/Users/bexgboost/Library/Caches/pypoetry" experimental.system-git-client = false installer.max-workers = null installer.modern-installation = true installer.no-binary = null installer.parallel = true keyring.enabled = true solver.lazy-wheel = true virtualenvs.create = true virtualenvs.in-project = null virtualenvs.options.always-copy = false virtualenvs.options.no-pip = false virtualenvs.options.no-setuptools = false virtualenvs.options.system-site-packages = false virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/bexgboost/Library/Caches/pypoetry/virtualenvs virtualenvs.prefer-active-python = false virtualenvs.prompt = "{project_name}-py{python_version}" warnings.export = true

在第一行中,我們看到了通往詩歌緩存的路徑。它主要用於存儲下載的包分發和虛擬環境。您創建的任何虛擬環境都會默認存儲在這裡。如果您想要更改這一點,可以運行以下命令:

$ poetry config virtualenvs.path path/to/new/virtualenv/dir

另一個重要的配置是安裝過程中使用的核心數量。默認情況下設置為四個,但我們可以通過利用所有 CPU 核心使其運行得更快。首先,運行 os.cpu_count() 在 Python 解釋器中查找您機器的核心數量。然後,設置輸出:

$ poetry config installer.max-workers = 10

一個可選的配置是在您的工作目錄或緩存中創建虛擬環境。這是通過virtualenvs.in-project 選項 來控制的。如果您將其設置為 True,.venv 目錄將始終在您的工作目錄中創建:

$ poetry config virtualenvs.in-project true

使用 Poetry 創建新項目

讓我們深入了解創建新 Poetry 項目的關鍵步驟,並了解其核心配置文件。

初始化新的 Poetry 項目

詩歌使用通常以使用poetry new 命令創建新項目開始:

$ poetry new explore-poetry $ cd explore-poetry

該命令創建一個explore-poetry 目錄,其中包含以下文件和目錄:

explore-poetry ├── pyproject.toml ├── README.md ├── explore-poetry │ └── __init__.py └── tests └── __init__.py

此目錄結構遵循Python最佳實踐:

  • pyproject.toml:定義專案元數據和依賴關係的主要配置文件
  • README.md:解釋專案的文件
  • explore-poetry/:包含主要套件代碼的源代碼目錄,並使用 __init__.py 使其成為一個套件
  • tests/:測試文件目錄,並使用 __init__.py 使其成為一個包(可導入)

理解 pyproject.toml

這裡,pyproject.toml 文件需要仔細關注,因為它是 Poetry 生成的唯一非空文件:

[tool.poetry] name = "explore-poetry" version = "0.1.0" description = "" authors = ["BexTuychiev <[email protected]>"] readme = "README.md" [tool.poetry.dependencies] python = "^3.8" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api"

這個檔案組織了您的項目及其依賴項目。它使用 Tom’s Obvious, Minimal Language,這已被確認為Python套件的標準配置語言,根據 PEP 518

所有pyproject.toml文件被分成稱為的部分,使用方括號如tool.poetrybuild-system。Poetry使用這些表來管理依賴項、項目構建要求或執行其他任務。

在執行接下來部分中列出的 Poetry 指令時,pyproject.toml 檔案將會被自動更新。

在 Poetry 中使用虛擬環境

在這部分中,一旦設置完成,您將了解如何管理 Poetry 中的虛擬環境的方方面面。您將學會為什麼虛擬環境很重要,Poetry 如何自動處理它們,以及用於操作它們的基本指令,如創建、啟用和切換。您還將學習如何使用 Poetry 管理 Python 版本。

創建和啟用虛擬環境

當您第一次安裝Poetry時,它並不附帶任何內建環境,這可以從運行poetry env list時的空白輸出看出:

$ poetry env list # no output

但一旦您開始使用poetry add package-name添加依賴項(稍後會談到更多),它將自動在緩存目錄中為該項目創建環境。例如,讓我們嘗試將requests作為一個依賴項:

$ poetry add requests

您應該會收到類似以下內容的輸出:

Creating virtualenv explore-poetry--I9GJYUn-py3.8 in /Users/bexgboost/Library/Caches/pypoetry/virtualenvs Using version ^2.32.3 for requests Updating dependencies Resolving dependencies... (2.5s) Package operations: 5 installs, 0 updates, 0 removals - Installing certifi (2024.8.30) - Installing charset-normalizer (3.4.0) - Installing idna (3.10) - Installing urllib3 (2.2.3) - Installing requests (2.32.3) Writing lock file

第一行表示詩歌在快取中創建了環境。接下來的幾行通知依賴於requests已成功解析,並生成了一個鎖定文件(稍後會詳細說明)。

請注意環境名稱:explore-poetry--I9GJYUn-py3.8。該名稱包括專案目錄名稱,後跟唯一ID,然後是環境正在使用的Python版本。

下次您添加依賴時,Poetry 將自動使用此環境來安裝套件:

$ poetry add beautifulsoup4 Using version ^4.12.3 for beautifulsoup4 Updating dependencies Resolving dependencies... (1.1s) Package operations: 2 installs, 0 updates, 0 removals - Installing soupsieve (2.6) - Installing beautifulsoup4 (4.12.3) Writing lock file

使用 Poetry 時,您的終端機不會顯示哪個 Poetry 虛擬環境是活動的。要查看此信息,您需要運行 poetry env list

$ poetry env list explore-poetry--I9GJYUn-py3.8 (Activated)

要與活動的 Poetry 環境交互,您可以運行 poetry shell

$ poetry shell

該命令在當前 shell 會話中打開一個新的 shell 會話,您可以執行像 pythonpytest 這樣的命令。

例如,執行 Python 腳本:

$ poetry shell $ python script.py

運行像 Streamlit 這樣的開發框架:

# 在 shell 內部 $ streamlit run app.py

之後,您可以通過調用exit來退出Shell。

或者,您可以運行Poetry shell中的命令而無需進入該Shell,方法是使用poetry run

$ poetry run python script.py $ poetry run streamlit run app.py

配置Python版本

當你運行 poetry addpoetry install 時,Poetry會自動使用你在 pyproject.toml 文件中指定的Python版本。若要指定不同的Python版本,你可以運行 env use 命令:

$ poetry env use python3.11

請注意,要使該命令正常工作,必須在您的機器上全系統安裝Python 3.11。

檢查Poetry是否正在使用具有新Python版本的環境:

$ poetry env list explore-poetry--I9GJYUn-py3.11 (Activated) explore-poetry--I9GJYUn-py3.8

注意新環境已自動附加到我們的項目(ID相同)。配置Python版本後,您可以刪除具有其他版本的環境以釋放磁盤空間:

$ poetry env remove python3.8

刪除環境時,只需指定Python版本。您也可以刪除所有環境並從頭開始:

$ poetry env remove --all

請注意,--all 標籤會刪除當前專案關聯的所有環境,而不是其他專案的環境。

如果您正在進行團隊專案,通常最好將虛擬環境保留在專案目錄中:

$ poetry config virtualenvs.in-project true

如果緩存中已經存在該專案的環境,此命令將不會產生任何效果。要創建本地環境,請先從緩存中刪除所有現有環境。

這將在您的工作目錄中創建一個.venv文件夾,您應將其添加到您的.gitignore文件中。

使用Poetry管理依賴項

依賴項管理是Poetry的強項。它提供了全面的功能來指定、安裝和管理依賴項,使您永遠不會遇到困擾的依賴衝突。

在這一部分,您將了解如何添加和安裝依賴項,創建依賴項組,依賴項規範語法在pyproject.toml和鎖定文件。

在Poetry中添加依賴項

使用Poetry時,您將使用poetry add package-name命令從PyPI安裝包,而不是使用pip install。這樣做有幾個好處:

  1. 自動將包添加到pyproject.toml並帶有正確的版本約束
  2. 更新鎖定文件以確保可重現的構建
  3. 解析依賴關係以避免衝突
  4. 在虛擬環境中安裝套件及其所有相依項目

例如,讓我們首先將 Numpy 添加為相依項目:

$ poetry add numpy

立即,您應該收到一個依賴解析衝突的訊息,指出正在安裝的 Numpy 版本與您的 Python 版本不相容。原因是當我們切換到 Python 3.11 環境時,我們沒有更新 pyproject.toml 檔案。現在,它看起來像這樣:

[tool.poetry.dependencies] python = "^3.8" requests = "^2.32.3" beautifulsoup4 = "^4.12.3"

插入符號 ^ 用於表示我們的 explore-poetry 項目兼容任何 Python 版本,直到 Python 4,但 Numpy 的版本範圍僅支持介於 3.8 和 3.12 之間的 Python 版本,這是一個更狹窄的範圍。 衝突錯誤來自這個事實。

因此,為了解決錯誤,您應將 Python 版本範圍更新如下:

python = ">=3.8, <3.12"

一旦您做了這個更改,poetry add numpy 命令應該能正常工作。

您剛剛觀察到 Poetry 的最佳功能之一 – 在安裝任何套件之前捕捉版本衝突,而不是像 pip 之後再通知您版本不相容的問題。

指定依賴版本的語法

詩歌使用強大的語法來指定各種版本,以確保最佳的依賴關係同步。以下是最常使用的符號:

  1. 插入符號 (^):允許更新補丁和次要版本,但不包括主要版本。例如:^1.2.3 允許從1.2.3更新到1.9.9,但不包括2.0.0。
  2. 波浪符號 (~):僅允許更新補丁版本。例如:~1.2.3 允許從1.2.3更新到1.2.9,但不包括1.3.0。
  3. 精確版本:指定精確的版本號碼。示例:1.2.3僅允許版本1.2.3
  4. 大於(>):允許指定版本之上的任何版本。示例:>1.2.3允許1.2.4,1.3.0,2.0.0等。
  5. 小於(<):允許任何指定版本以下。例如:<2.0.0 允許任何低於 2.0.0 的版本。
  6. 大於或等於(>=):允許指定版本及以上。例如:>=1.2.3 允許 1.2.3 及任何更高的版本。
  7. 小於或等於(<=):允許指定版本及以下。例如:<=2.0.0 表示 2.0.0 及任何更低的版本。
  8. 版本範圍:使用逗號結合約束條件。例如:>=1.2.3,<2.0.0 表示版本從 1.2.3 到 1.9.9
  9. 萬用字元 (*): 匹配任何版本。例如: 1.2.* 匹配以1.2開頭的任何版本

當然,您可以混合配對這些來滿足您的需求。

在Poetry中創建依賴組

在具有許多移動組件的複雜項目中,您通常會處理不同類別的依賴關係。

舉例來說,在一個機器學習項目中,您通常會為數據輸入、數據清理、特徵工程、模型訓練、部署和監控創建不同的流水線和組件。更不用說,您還需要完成文檔編寫和運行測試。所有這些步驟都有各自的工具生態系統,混合它們的依賴項會使最終發行包變得臃腫。

使用Poetry,您可以創建具有任意名稱的依賴組,以便只在需要時安裝它們。或者最好的部分是——您的包的用戶也可以選擇安裝他們需要的部分。

$ poetry add --group ui streamlit plotly dash $ poetry add --group dev black flake8 isort mypy pylint

上述命令創建兩個依賴組,uidev(如果它們不存在),並在 pyproject.toml 中創建兩個子表:

[tool.poetry.dependencies] python = "^3.11" requests = "^2.32.3" beautifulsoup4 = "^4.12.3" numpy = "^2.1.3" [tool.poetry.group.ui.dependencies] streamlit = "^1.39.0" plotly = "^5.24.1" dash = "^2.18.2" [tool.poetry.group.dev.dependencies] black = "^24.10.0" flake8 = "^7.1.1" isort = "^5.13.2" mypy = "^1.13.0" pylint = "^3.3.1"

即使依賴組被分開,它們仍然相互解析。換句話說,如果有一個dev依賴與ui中的一個套件產生衝突,Poetry 將無法運行安裝。

在某些情況下,您可以創建可選的依賴組或使現有組件成為可選的,這樣當用戶重新創建您的項目環境時,它們就不會被默認安裝。要實現這一點,您需要在pyproject.toml文件中創建一個新的子表。例如,我們將使ui組成為可選的:

[tool.poetry.group.ui] optional = true [tool.poetry.group.ui.dependencies] streamlit = "^1.39.0" plotly = "^5.24.1" dash = "^2.18.2"

通過將optional 參數設置為 true 後再宣告該組的依賴項。

使用 poetry.lock 文件重現一個 Poetry 項目

如果有人克隆您的 GitHub 存儲庫,其中包含一個 Poetry 項目,他們可以通過運行一個命令來為您的項目重新創建一個完美的虛擬環境:poetry install

install命令使用更全面的poetry.lock文件。与pyproject.toml不同,锁定文件列出了:

  • 主要依賴項的確切版本列在 pyproject.toml
  • 主要依賴項的依賴項(傳遞依賴項)的確切版本

例如,requests 依賴於 urllib3certificharset-normalizer 以及 idna。如果沒有鎖定文件,這些子依賴關係可能會在不同的機器上解析為不同的版本。

鎖定文件確保團隊中的每個人都獲得相同的依賴版本,防止“在我的機器上運行正常”的問題。

poetry add和poetry install之間的區別

我們將解釋addinstall命令在Poetry中的區別,並附帶一個用例。

假設您正在進行一個欺詐檢測項目。您添加了初始依賴項:

$ poetry add pandas scikit-learn

這將包添加到鎖定和pyproject.toml文件中。然後,您的同事克隆存儲庫:

$ git clone fraud-detection-repo-link $ cd fraud-detection $ poetry install

他們運行install命令來安裝鎖定文件中列出的所有內容。

後來,您需要添加新的包:

$ poetry add xgboost

您的同事拉取更改:

$ git pull $ poetry install

他们运行 install 命令来安装新的软件包。因此,

  • 在添加新的依赖项时,请使用 poetry add
  • 使用poetry install來設置現有項目
  • 始終提交pyproject.tomlpoetry.lock到版本控制

使用poetry install命令安裝依賴組

早些时候,我们学习了如何在Poetry中对依赖项进行分组。当您运行poetry install时,默认情况下会安装所有非可选组,这可能并非在所有情况下都是您想要的。

例如,您可能只是在克隆一个存储库以便处理文档。或者您希望处理存储库的主要代码,但不包括文档和测试方面。 install命令足够灵活,可以涵盖所有这些情况:

除外特定群組:

$ poetry install --without ui,dev

安裝選擇性群組:

# 安裝選擇性文件群組 $ poetry install --with docs

僅安裝特定群組:

$ poetry install --only ui

僅安裝專案的運行時依賴(在群組外提到的依賴,使用純poetry add package 命令添加):

$ poetry install --only main

在Poetry中移除依賴

刪除依賴項非常簡單,只需使用remove命令:

$ poetry remove requests

這將從主要項目依賴項中刪除requests。要從組依賴項中刪除套件,可以再次使用--group標記:

$ poetry remove streamlit --group ui

remove命令會乾淨地卸載套件,以及其傳遞相依性。

Publishing a Project with Poetry to PyPI

如果您的項目準備好進行分發,將其發佈到 PyPI(Python Package Index)允許其他開發人員通過pip輕鬆安裝和使用您的代碼。Poetry僅需兩個命令即可輕鬆完成此過程:

$ poetry build # 創建發行版 $ poetry publish # 發佈到 PyPI

然而,在執行這些命令之前,您應正確設置您的 PyPI 憑證。首先,在以下位置創建您的帳戶:

  1. PyPI
  2. TestPyPI

使用您的憑證配置 Poetry:

$ poetry config pypi-token.pypi your-pypi-token $ poetry config pypi-token.testpypi your-test-pypi-token

現在,先測試您的套件:

# 配置 TestPyPI 存儲庫 $ poetry config repositories.testpypi https://test.pypi.org/legacy/ # 發布到 TestPyPI $ poetry build $ poetry publish -r testpypi

在將項目發布到 TestPyPI 後,您可以嘗試安裝您的套件以測試一切是否運作正常:

$ pip install --index-url https://test.pypi.org/simple/ your-package-name

如果一切順利,您可以發布到 PyPI 本身:

$ poetry publish

使用 Poetry 時的最佳實踐

在使用 Poetry 時,有許多需要注意的地方和最佳實踐,當然,我們無法在一篇文章中全部提及。但以下是一些您可以立即應用的常見實踐:

  1. 始終使用虛擬環境 – Poetry 會自動為每個項目創建虛擬環境
  2. 將您的 pyproject.toml 檔案放在版本控制下,但排除 poetry.lock 供函式庫使用
  3. poetry.lock 包含在版本控制中,以確保應用程式具有可重現的構建
  4. 使用語義化版本號來管理您的套件版本(主版本.次要版本.修訂版本)。您可以使用poetry version patch/minor/major指令來將套件版本增加一個單位。例如,poetry version major會將版本從0.2.0升級到1.0.0在您的pyproject.toml文件中。
  5. 仔細指定依賴版本約束以避免衝突
  6. 定期使用 poetry update 更新依賴,但更新後要進行充分測試
  7. 使用 poetry add --group dev 添加開發依賴以保持它們分開
  8. pyproject.toml文件中使用註釋記錄所有依賴項的目的
  9. 運行 poetry check 在提交之前驗證 pyproject.toml 的語法。您也可以考慮 pre-commit hooks
  10. 使用poetry export來生成requirements.txt當其他工具需要時。
  11. 保持生產依賴項目的最小化 – 將可選功能移至額外部分
  12. 在發布之前在乾淨環境中測試您的套件安裝
  13. 在將程式發佈到主 PyPI 存儲庫之前,請使用 TestPyPI
  14. 維護清晰的 CHANGELOG.md 以跟蹤版本更改
  15. 使用 poetry run 來執行腳本以確保正確的環境使用

結論和下一步操作

Poetry 通過提供強大直觀的解決方案,從而使 Python 依賴管理方式發生革命,應對了常見的套件管理挑戰。它強大的依賴解析、虛擬環境管理和項目發佈功能,使其成為現代 Python 開發中不可或缺的工具。

要繼續 Python 開發之旅,請考慮探索這些全面的學習路徑:

請記住,有效的依賴管理只是專業Python開發的一個方面。隨著您作為開發人員的成長,像Poetry這樣的工具將幫助您建立更易維護和可靠的Python項目。

Source:
https://www.datacamp.com/tutorial/python-poetry