【後端開發】告別 pip 與 poetry!PDM 讓你的 Python 專案管理更有效率

前言

身為 Python 開發者,我們都知道使用 pip 安裝環境有多麻煩。每次建立新專案時,都要手動設定虛擬環境,跟擔心套件版本衝突的問題,雖然後來出現了 poetry 這類的工具,但對於一些較大的專案來說,poetry 的效能還是偏慢,在設定上也較複雜。這就是為什麼我後來改使用 PDM 。

PDM 的誕生其實和 PEP 582 這個提案有關。這個提案是希望能夠標準化 Python 的套件管理方式,新增 __pypackages__(類似 JavaScript 的 node_modules 資料目錄)。雖然這個提案最後沒有被接受,但 PDM 還是支援這個用法,也支援許多實用的功能。

PDM 特色

首先 PDM 的主要特色就是它的安裝速度超快!這是因為它採用了並行下載的方式,而且它會自己幫你處理套件之間的相依關係。

另外一個很棒的特點是它不需要配置虛擬環境。當你使用 PDM 時,它會自動在專案目錄下建立一個 __pypackages__ 資料夾,所有的套件都會安裝在這裡,不用另外選擇要用哪個虛擬環境。

如何安裝 PDM?

我的電腦是 Mac,所以使用 Homebrew 安裝,或你是使用 Windows

pip install pdm

# 關閉虛擬環境,使用 pep 582
pdm config python.use_venv false

初始化專案

安裝完成後,我們使用 VSCode 建立一個新專案,並輸入:

pdm init

pdm 會列出你現在現有的 Python 版本讓你選擇,這裡我使用 3.10 的 Python,其他按 Enter 使用預設選項就可以了。

Creating a pyproject.toml for PDM...
Please enter the Python interpreter to use
  1. cpython@3.10 (/opt/homebrew/bin/python3.10)
Please select (0): 1
Project name (flask-demo): 
Project version (0.1.0): 
Do you want to build this project for distribution(such as wheel)?
If yes, it will be installed by default when running `pdm install`. [y/n] (n): 
License(SPDX name) (MIT): 
Author name (yui): yui
Author email (): 
Python requires('*' to allow any) (==3.10.*):

完成後專案就會出現幾個檔案:

├── README.md       
├── pyproject.toml  
├── .pdm-python   
├── .gitignore
├── pdm.lock
├── .venv/ 
├── src/            # 專案主要程式碼
└── tests/          # 測試程式碼
    └── __init__.py
  • pyproject.toml:專案的設定檔案(包括專案的名稱、版本、依賴套件、Python 版本需求)
  • pdm.lock:詳細記載所有套件的(包含相依套件)的版本號
  • .pdm-python:記錄了專案使用的 Python 版本路徑(可以任意切換),PDM 會透過這個檔案來確保你使用正確的 Python 環境。

如何使用 PDM 新增套件?

PDM 下載套件的指令如下:

pdm add <package_name>

讓我們來下載 Flask 套件,Flask 是 Python 開發網頁的其中一種框架,可以看到 pdm 幫你把許多相依套件也下載了。

$pdm add flask

Adding packages to default dependencies: flask
  0:00:02 🔒 Lock successful.  
Changes are written to pyproject.toml.
Synchronizing working set with resolved packages: 7 to add, 0 to update, 0 to remove

   Install flask 3.1.0 successful
   Install blinker 1.9.0 successful
   Install itsdangerous 2.2.0 successful
   Install markupsafe 3.0.2 successful
   Install click 8.1.8 successful
   Install werkzeug 3.1.3 successful
   Install jinja2 3.1.5 successful

  0:00:01 🎉 All complete! 7/7

然後多了一個 __pypackages__ 目錄用來存放我們的套件,取代傳統的虛擬環境。

pdm tutorial 1

再來看看 pyproject.toml dependencies 的地方,雖然剛剛下載了很多相依套件,但真正的 dependencies 只有 flask 套件,這就是 pdm 內建的相依套件管理。

[project]
name = "flask-demo"
version = "0.1.0"
description = "Default template for PDM package"
authors = [
    {name = "yui", email = ""},
]
dependencies = ["flask>=3.1.0"]
requires-python = "==3.10.*"
readme = "README.md"
license = {text = "MIT"}


[tool.pdm]
distribution = false

使用 PDM 安裝專案依賴

如果今天我們接手了一個由 PDM 管理套件的專案,我們可以輸入下面的指令,PDM 就會根據 pdm.lock 檔案來安裝專案的所有套件。

pdm install

在執行 pdm install 時,PDM 會自動幫你安裝 Flask 所需的所有相依套件,像是 Werkzeug、Jinja2、click 等等。這些相依套件的版本資訊都會被詳細記錄在 pdm.lock 檔案中。

它在管理相依性時採用了「聲明式」的方式,讓開發者只需要關注直接相依的套件,其他的相依關係都交給 PDM 來處理。可以讓專案設定檔更容易維護,也大幅降低了版本衝突的可能性。

這種設計特別適合團隊合作,當新成員加入專案時,可以一眼就看出專案主要使用了哪些套件,而不會被大量的間接相依套件混淆。同時 PDM 的 lock 檔案又能確保所有人使用的是完全相同的套件版本,讓開發環境的一致性得到很好的保障。

如何使用 PDM 移除套件?

pdm remove <package_name>

PDM 進階技巧

1.使用群組依賴管理開發套件

當我們使用 -d--dev 參數安裝套件時,PDM 會將這些套件加入開發依賴群組。很適合用來區分生產環境和開發環境

如果我們想要添加開發時才需要的套件,可以這樣做:

pdm add -d pytest

可以看到 pyproject.toml 多了:

dependencies = ["flask>=3.1.0"]  # 生產環境需要的套件

[dependency-groups]
dev = [
    "pytest>=8.3.4",  # 開發環境需要的套件
]

我們可以使用不同的指令來管理這些套件:

pdm install   # 安裝所有套件(包含開發套件)
pdm install --prod    # 只安裝生產環境套件
pdm install --dev     # 只安裝開發環境套件

2.建立多個依賴群組

除此之外,我們還可以將套件分類,這邊的範例我把測試和程式碼檢查套件分開:

pdm add -G <group_name> <package_name>

pdm add -G test pytest          # 測試群組
pdm add -G lint black flake8    # 程式碼檢查群組
[project.optional-dependencies]
test = [
    "pytest>=8.3.4",
]
lint = [
    "black>=23.0.0",
    "flake8>=6.0.0",
]

3.自訂腳本命令

如果想要自訂指令可以在 scripts 中加入:

[tool.pdm.scripts]
start = "flask run"
test = "pytest tests/ --cov"
lint = {composite = ["black .", "flake8"]}

使用方式:

pdm run start   # 執行 flask run
pdm run test    # 運行測試
pdm run lint    # 執行程式碼檢查

也可以加入環境變數:

[tool.pdm.scripts]
dev = {cmd = "flask run", env = {"FLASK_ENV" = "development"}}

常見問題解答

PDM 可以和現有的 virtual environment 一起使用嗎?

可以,但建議選擇其中一種方式。若要使用 virtual environment,需設定:

pdm config python.use_venv true

如何在 Docker 中使用 PDM?

在 Dockerfile 中下載 pdm:

COPY pyproject.toml pdm.lock ./
RUN pip install pdm
RUN pdm install --prod --no-lock  # 只下載 prod 指定的套件

如何從 requirements.txt 遷移到 PDM?

執行下列指令自動轉換:

pdm import requirements.txt 

如何查看已安裝的套件列表?

pdm list  # 查看相依套件

pdm list --graph  # 查看相依關係圖

如何更新所有套件?

pdm update

結語

現在我們了解了怎麼使用 pdm 管理環境和套件,下一步我們就可以開始寫 API 囉!

完整教學:APIFlask 完整入門指南:更優雅的 RESTful API 框架

參考網站