在昨天的文章【Python】通過Editable Install
模式詳解,解決Python開發總是import出錯的問題 中, 我們提到了Python項目的配置文件requirements.txt
、setup.py
、pyproject.toml
。在昨天的解決方案中, 我們同時維護了這三個文件。 由同學就問:真的需要這么復雜的同時維護三個文件嗎? 今天,田辛老師就來詳細解釋一下這三個文件。 包括他們的核心用途、演變歷史等等。 希望通過這篇文章, 讀者思考在你的項目中, 是否需要保留他們。
1. requirements.txt
: 最最簡單的依賴列表
定位:最基礎的依賴聲明文件,通常用于直接安裝依賴。
用途:
- 列出項目運行所需的第三方包及其版本(例如
requests==2.25.1
)。 - 通過
pip install -r requirements.txt
一鍵安裝依賴。 - 常用于開發環境或生成依賴快照(如
pip freeze
)。
局限性:
- 僅記錄依賴包,不區分開發依賴、生產依賴或操作系統級的依賴。
- 無法定義包的安裝方式(例如從Git倉庫或本地路徑安裝)。
- 與項目打包(如生成
.whl
或上傳到PyPI
)無關。
2. setup.py
:傳統的打包配置
2.1. 定位:
基于 setuptools
的打包工具配置文件,用于構建和分發Python
包。
2.2. 用途:
- 定義項目元數據(名稱、版本、作者等)。
- 聲明依賴(
install_requires
)、開發依賴(extras_require
)以及可執行腳本。 - 通過
python setup.py install
或pip install .
安裝本地包。
2.3. 示例片段:
from setuptools import setupsetup(name="tdouya_tools",version="0.1",install_requires=["requests>=2.25"],extras_require={"dev": ["pytest"]},
)
2.4. 缺點:
- 配置復雜,需要編寫
Python
代碼(而非聲明式配置)。 - 依賴動態執行(可能存在安全隱患)。
- 無法直接支持現代構建后端(如
poetry
或flit
)。
3. pyproject.toml
:現代的統一配置
3.1. 定位:
PEP 518
引入的標準化配置文件,旨在統一項目構建和元數據配置。
3.2. 用途:
- 指定構建系統的依賴(如 setuptools、poetry 或 flit)。
- 聲明項目元數據、依賴及版本約束(遵循PEP 621標準)。
- 支持動態依賴分離(生產依賴、開發依賴、測試依賴等)。
3.3. 示例片段
使用 PEP 621 格式
[project]
name = "my_project"
version = "0.1"
dependencies = ["requests>=2.25"][project.optional-dependencies]
dev = ["pytest"]
優勢:
- 聲明式配置:更簡潔且易于維護。
- 兼容性:支持現代工具鏈(如
poetry
、pipenv
)。 - 擴展性:可整合代碼格式化、測試配置等其他工具(如
black
、coverage
)。
4. 三者是否需要共存?
田老師回答: 通常不需要,但取決于項目需求和工具鏈。對于某些場景,同時保留 requirements.txt 和 setup.py 可能帶來實際價值。
4.1. 場景分析
4.1.1. 傳統項目(僅用 setuptools
)
- 需要
setup.py
+requirements.txt
:setup.py
用于定義打包元數據和依賴(install_requires
),適合發布到PyPI
。requirements.txt
可以細化開發環境依賴(如測試框架pytest
、代碼格式化工具black
),并通過pip install -r requirements.txt
快速安裝。- 優勢:職責分離,
setup.py
關注生產依賴和分發,requirements.txt
管理開發工具和環境復現。
這也是田辛老師的項目中, 往往這兩個文件同時存在的原因。
4.1.2. 兼容舊工具鏈或腳本
- 許多CI/CD流水線、自動化腳本或開發者習慣依賴 requirements.txt 快速安裝依賴。
- 保留 setup.py 可以兼容 python setup.py install 等傳統構建命令,避免破壞遺留工作流程。
- 示例:
# 開發時安裝開發依賴 pip install -r requirements.txt # 構建時通過 setup.py 安裝生產包 python setup.py build
4.1.3. 漸進式遷移到 pyproject.toml
在過渡階段,同時保留 setup.py
和 requirements.txt
可降低遷移風險:
pyproject.toml
定義核心配置和構建后端。setup.py
作為備用接口(例如兼容未完全支持PEP 621
的工具)。requirements.txt
繼續用于開發環境依賴安裝。
4.1.4. 依賴管理的靈活性
4.1.4.1. 細粒度控制:
- 在 requirements.txt 中指定復雜依賴(如 Git 倉庫、本地路徑或特定系統級包)。
- 在 setup.py 的 install_requires 中僅聲明最小化生產依賴,保持分發包的輕量性。
4.1.4.2. 示例:
# setup.py 中僅保留核心依賴
install_requires = ["requests>=2.25"]
# requirements.txt 包含開發工具和環境約束
pytest==7.4.0
black==23.9.1
-e . # 以可編輯模式安裝當前包
4.1.4.3. 關鍵決策點
- 是否依賴舊工具或腳本:若團隊或工具鏈重度依賴
requirements.txt
,保留它可以減少遷移成本。 - 是否需要快速環境復現:
requirements.txt
結合pip freeze
能生成精確的依賴快照,適合快速復制開發環境。 - 是否需要兼容非打包場景:例如在
Dockerfile
中直接使用requirements.txt
安裝依賴,而非通過包構建流程。
5. 最佳實踐建議
5.1. 新項目優先使用 pyproject.toml
通過 PEP 621
或工具(如 poetry
)定義元數據和依賴,無需 setup.py
或 requirements.txt
。
5. 2. 舊項目逐步遷移
保留 setup.py
但逐步將配置轉移到 pyproject.toml
,例如使用 setuptools
的 [project] 表。
5.3 . 區分 requirements.txt
的使用場景
如果仍需用它,可以自動生成:
# 通過 poetry 生成
poetry export -f requirements.txt --output requirements.txt
5.4 . 避免重復聲明依賴
不要同時在 setup.py
和 pyproject.toml
中聲明依賴,否則會導致維護負擔。
6. 結論
在現代1Python1生態中,pyproject.toml
是未來的方向,能夠取代 setup.py
和 requirements.txt
的大部分功能。對于新項目,推薦僅使用 pyproject.toml
并結合工具(如 poetry
)管理依賴和構建流程。舊項目可視情況逐步遷移,無需強制三者共存。最終目標是簡化配置、減少冗余,并擁抱標準化。