最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用pyproject.toml構(gòu)建現(xiàn)代化Python項(xiàng)目的詳細(xì)步驟

 更新時(shí)間:2026年05月07日 09:51:36   作者:像風(fēng)一樣自由2020  
如果你曾經(jīng)接觸過 Python 項(xiàng)目,可能對(duì) setup.py、setup.cfg、requirements.txt 這些文件并不陌生,但隨著 Python 生態(tài)的發(fā)展,這種分散的配置方式逐漸暴露出諸多問題,pyproject.toml 的出現(xiàn)正是為了解決這些痛點(diǎn),本文詳細(xì)講解如何從零開始配置 pyproject.toml

前言

如果你曾經(jīng)接觸過 Python 項(xiàng)目,可能對(duì) setup.py、setup.cfg、requirements.txt 這些文件并不陌生。但隨著 Python 生態(tài)的發(fā)展,這種分散的配置方式逐漸暴露出諸多問題:配置分散、格式不統(tǒng)一、工具兼容性差等。

pyproject.toml 的出現(xiàn)正是為了解決這些痛點(diǎn)。它是 Python 項(xiàng)目的現(xiàn)代化配置標(biāo)準(zhǔn),由 PEP 518、PEP 621 等規(guī)范定義,旨在提供一個(gè)統(tǒng)一的、聲明式的項(xiàng)目配置文件。

本文將以一個(gè)實(shí)際項(xiàng)目 PyImage Split(圖片拆分工具)為例,詳細(xì)講解如何從零開始配置 pyproject.toml,讓你的 Python 項(xiàng)目更加規(guī)范、現(xiàn)代化。

為什么選擇 pyproject.toml

傳統(tǒng)方式的問題

pyproject.toml 出現(xiàn)之前,一個(gè)典型的 Python 項(xiàng)目可能包含以下配置文件:

my_project/
├── setup.py              # 項(xiàng)目元數(shù)據(jù)和構(gòu)建配置
├── setup.cfg             # 部分配置的聲明式版本
├── requirements.txt      # 運(yùn)行依賴
├── requirements-dev.txt  # 開發(fā)依賴
├── MANIFEST.in           # 打包文件清單
├── pytest.ini            # pytest 配置
├── .flake8               # flake8 配置
├── .isort.cfg            # isort 配置
└── mypy.ini              # mypy 配置

這種方式存在以下問題:

  1. 配置分散:相關(guān)配置散落在多個(gè)文件中,難以維護(hù)
  2. 格式不統(tǒng)一:INI、CFG、TXT、Python 腳本混雜
  3. setup.py 的安全隱患:作為 Python 腳本,可能執(zhí)行任意代碼
  4. 依賴管理混亂:運(yùn)行依賴和開發(fā)依賴分離管理

pyproject.toml 的優(yōu)勢

  1. 統(tǒng)一配置:所有配置集中在一個(gè)文件
  2. 標(biāo)準(zhǔn)格式:使用 TOML 格式,語法清晰易讀
  3. 聲明式配置:無需執(zhí)行代碼,更安全
  4. 工具兼容:現(xiàn)代 Python 工具都支持
  5. PEP 標(biāo)準(zhǔn):官方推薦的配置方式

pyproject.toml 的基本結(jié)構(gòu)

一個(gè)完整的 pyproject.toml 通常包含以下幾個(gè)主要部分:

# 1. 構(gòu)建系統(tǒng)配置
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
# 2. 項(xiàng)目元數(shù)據(jù)
[project]
name = "my-project"
version = "0.1.0"
# ... 其他元數(shù)據(jù)
# 3. 可選依賴
[project.optional-dependencies]
dev = ["pytest", "black"]
# 4. 入口點(diǎn)
[project.scripts]
my-command = "my_package.main:main"
# 5. 項(xiàng)目鏈接
[project.urls]
Homepage = "https://github.com/..."
# 6. 構(gòu)建工具特定配置
[tool.setuptools]
# setuptools 相關(guān)配置
# 7. 其他工具配置
[tool.black]
line-length = 88
[tool.pytest.ini_options]
testpaths = ["tests"]

實(shí)戰(zhàn):配置 PyImage Split 項(xiàng)目

讓我們以 PyImage Split 項(xiàng)目為例,這是一個(gè)使用 PySide6 構(gòu)建的圖片查看和拆分工具。

項(xiàng)目結(jié)構(gòu)

pyimage_split/
├── pyproject.toml              # 項(xiàng)目配置文件
├── README.md                   # 項(xiàng)目說明
├── src/                        # 源代碼目錄
│   └── pyimage_split/          # 主包
│       ├── __init__.py         # 包初始化
│       └── main.py             # 主程序
└── tests/                      # 測試目錄
    └── test_main.py            # 單元測試

完整的 pyproject.toml

[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "pyimage-split"
version = "0.1.0"
description = "圖片查看和均勻拆分工具"
readme = "README.md"
license = {text = "MIT"}
authors = [
    {name = "Your Name", email = "your.email@example.com"}
]
requires-python = ">=3.8"
classifiers = [
    "Development Status :: 3 - Alpha",
    "Intended Audience :: End Users/Desktop",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.8",
    "Programming Language :: Python :: 3.9",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11",
    "Programming Language :: Python :: 3.12",
]
dependencies = [
    "PySide6>=6.5.0",
    "Pillow>=9.0.0",
]
[project.optional-dependencies]
dev = [
    "pytest>=7.0",
    "black>=23.0",
    "ruff>=0.1.0",
]
[project.scripts]
pyimage-split = "pyimage_split.main:main"
[project.urls]
Homepage = "https://github.com/yourusername/pyimage-split"
Documentation = "https://github.com/yourusername/pyimage-split#readme"
Repository = "https://github.com/yourusername/pyimage-split"
[tool.setuptools.packages.find]
where = ["src"]
[tool.black]
line-length = 88
target-version = ['py38', 'py39', 'py310', 'py311', 'py312']
[tool.ruff]
line-length = 88
select = ["E", "F", "W", "I"]
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = "test_*.py"

各配置部分詳解

1. [build-system] - 構(gòu)建系統(tǒng)配置

[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

這是 pyproject.toml必須包含的部分,由 PEP 518 定義。

字段說明
requires構(gòu)建項(xiàng)目所需的依賴包列表
build-backend指定構(gòu)建后端

常用構(gòu)建后端對(duì)比:

構(gòu)建后端特點(diǎn)適用場景
setuptools.build_meta功能全面,兼容性好通用項(xiàng)目
poetry.core.masonry.apiPoetry 生態(tài)使用 Poetry 管理的項(xiàng)目
flit_core.buildapi簡單輕量純 Python 包
hatchling現(xiàn)代化,功能豐富新項(xiàng)目推薦
pdm.backendPDM 生態(tài)使用 PDM 管理的項(xiàng)目

2. [project] - 項(xiàng)目元數(shù)據(jù)

這是項(xiàng)目的核心配置部分,由 PEP 621 定義。

基本信息

[project]
name = "pyimage-split"
version = "0.1.0"
description = "圖片查看和均勻拆分工具"
字段必需說明
name項(xiàng)目名稱,用于 pip 安裝
version版本號(hào),遵循 SemVer 規(guī)范
description簡短描述

項(xiàng)目命名規(guī)范:

  • 使用小寫字母和連字符(如 pyimage-split
  • 包名使用下劃線(如 pyimage_split
  • 避免與已有 PyPI 包重名

README 和許可證

readme = "README.md"
license = {text = "MIT"}

readme 支持多種格式:

  • 字符串:readme = "README.md"
  • 指定類型:readme = {file = "README.rst", content-type = "text/x-rst"}

license 的寫法:

  • 簡單文本:license = {text = "MIT"}
  • 引用文件:license = {file = "LICENSE"}

作者信息

authors = [
    {name = "Your Name", email = "your.email@example.com"}
]
maintainers = [
    {name = "Maintainer Name", email = "maintainer@example.com"}
]

Python 版本要求

requires-python = ">=3.8"

常見寫法:

  • >=3.8:3.8 及以上
  • >=3.8,<4.0:3.8 到 3.x
  • ~=3.8:兼容 3.8.x

分類器 (Classifiers)

classifiers = [
    "Development Status :: 3 - Alpha",
    "Intended Audience :: End Users/Desktop",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.8",
    "Programming Language :: Python :: 3.9",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11",
    "Programming Language :: Python :: 3.12",
]

分類器用于在 PyPI 上對(duì)項(xiàng)目進(jìn)行分類,完整列表見:https://pypi.org/classifiers/

常用分類器:

類別示例
開發(fā)狀態(tài)Development Status :: 3 - Alpha
目標(biāo)用戶Intended Audience :: Developers
許可證License :: OSI Approved :: MIT License
操作系統(tǒng)Operating System :: OS Independent
編程語言Programming Language :: Python :: 3
主題Topic :: Software Development :: Libraries

3. dependencies - 項(xiàng)目依賴

dependencies = [
    "PySide6>=6.5.0",
    "Pillow>=9.0.0",
]

版本約束語法:

語法含義示例
>=大于等于requests>=2.28.0
<=小于等于requests<=3.0.0
==精確版本requests==2.28.1
!=排除版本requests!=2.28.0
~=兼容版本requests~=2.28.0 (等于 >=2.28.0,<2.29.0)
*通配符requests==2.28.*

組合使用:

dependencies = [
    "requests>=2.28.0,<3.0.0",
    "numpy>=1.20.0; python_version>='3.9'",  # 條件依賴
]

4. [project.optional-dependencies] - 可選依賴

[project.optional-dependencies]
dev = [
    "pytest>=7.0",
    "black>=23.0",
    "ruff>=0.1.0",
]
docs = [
    "sphinx>=5.0",
    "sphinx-rtd-theme>=1.0",
]
all = [
    "pyimage-split[dev,docs]",
]

安裝方式:

# 安裝開發(fā)依賴
pip install -e ".[dev]"
# 安裝文檔依賴
pip install -e ".[docs]"
# 安裝所有可選依賴
pip install -e ".[all]"

5. [project.scripts] - 命令行入口點(diǎn)

[project.scripts]
pyimage-split = "pyimage_split.main:main"

這會(huì)創(chuàng)建一個(gè)名為 pyimage-split 的命令,執(zhí)行時(shí)調(diào)用 pyimage_split.main 模塊的 main 函數(shù)。

格式解析:

命令名 = "包名.模塊名:函數(shù)名"

安裝后可直接在命令行使用:

$ pyimage-split

其他入口點(diǎn)類型:

# GUI 腳本(Windows 下無控制臺(tái)窗口)
[project.gui-scripts]
pyimage-split-gui = "pyimage_split.main:main"

# 插件入口點(diǎn)
[project.entry-points."myapp.plugins"]
plugin1 = "mypackage.plugins:Plugin1"

6. [project.urls] - 項(xiàng)目鏈接

[project.urls]
Homepage = "https://github.com/yourusername/pyimage-split"
Documentation = "https://github.com/yourusername/pyimage-split#readme"
Repository = "https://github.com/yourusername/pyimage-split"
Changelog = "https://github.com/yourusername/pyimage-split/blob/main/CHANGELOG.md"
"Bug Tracker" = "https://github.com/yourusername/pyimage-split/issues"

這些鏈接會(huì)顯示在 PyPI 項(xiàng)目頁面上。

常用工具配置

[tool.setuptools] - Setuptools 配置

[tool.setuptools.packages.find]
where = ["src"]
include = ["pyimage_split*"]
exclude = ["tests*"]

使用 src 布局的項(xiàng)目需要指定 where = ["src"]。

動(dòng)態(tài)版本號(hào):

如果想從 __init__.py 讀取版本號(hào):

[project]
dynamic = ["version"]

[tool.setuptools.dynamic]
version = {attr = "pyimage_split.__version__"}

[tool.black] - 代碼格式化

[tool.black]
line-length = 88
target-version = ['py38', 'py39', 'py310', 'py311', 'py312']
include = '\.pyi?$'
exclude = '''
/(
    \.git
  | \.hg
  | \.mypy_cache
  | \.tox
  | \.venv
  | _build
  | buck-out
  | build
  | dist
)/
'''
配置項(xiàng)說明默認(rèn)值
line-length每行最大字符數(shù)88
target-version目標(biāo) Python 版本自動(dòng)檢測
include包含的文件模式\.pyi?$
exclude排除的文件模式常見緩存目錄

[tool.ruff] - 代碼檢查

Ruff 是一個(gè)用 Rust 編寫的快速 Python linter,可以替代 flake8、isort 等多個(gè)工具。

[tool.ruff]
line-length = 88
select = [
    "E",   # pycodestyle errors
    "F",   # pyflakes
    "W",   # pycodestyle warnings
    "I",   # isort
    "B",   # flake8-bugbear
    "C4",  # flake8-comprehensions
    "UP",  # pyupgrade
]
ignore = [
    "E501",  # line too long (handled by black)
]

[tool.ruff.isort]
known-first-party = ["pyimage_split"]

[tool.pytest.ini_options] - 測試配置

[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = "test_*.py"
python_classes = "Test*"
python_functions = "test_*"
addopts = "-v --tb=short"
markers = [
    "slow: marks tests as slow",
    "integration: marks tests as integration tests",
]
配置項(xiàng)說明
testpaths測試文件目錄
python_files測試文件名模式
addopts默認(rèn)命令行參數(shù)
markers自定義標(biāo)記

[tool.mypy] - 類型檢查

[tool.mypy]
python_version = "3.8"
warn_return_any = true
warn_unused_configs = true
ignore_missing_imports = true
[[tool.mypy.overrides]]
module = "tests.*"
ignore_errors = true

[tool.coverage] - 代碼覆蓋率

[tool.coverage.run]
source = ["src"]
branch = true
omit = ["tests/*"]
[tool.coverage.report]
exclude_lines = [
    "pragma: no cover",
    "def __repr__",
    "raise NotImplementedError",
    "if __name__ == .__main__.:",
]
show_missing = true

項(xiàng)目安裝與分發(fā)

本地開發(fā)安裝

# 進(jìn)入項(xiàng)目目錄
cd pyimage_split
# 創(chuàng)建虛擬環(huán)境
python -m venv venv
source venv/bin/activate  # Linux/macOS
# 或
venv\Scripts\activate  # Windows
# 可編輯模式安裝(推薦開發(fā)時(shí)使用)
pip install -e .
# 安裝開發(fā)依賴
pip install -e ".[dev]"

-e 參數(shù)表示可編輯模式(editable mode),修改源碼后無需重新安裝。

構(gòu)建分發(fā)包

# 安裝構(gòu)建工具
pip install build
# 構(gòu)建
python -m build

構(gòu)建完成后,dist/ 目錄下會(huì)生成:

  • pyimage_split-0.1.0.tar.gz:源碼分發(fā)包 (sdist)
  • pyimage_split-0.1.0-py3-none-any.whl:構(gòu)建分發(fā)包 (wheel)

發(fā)布到 PyPI

# 安裝 twine
pip install twine
# 檢查分發(fā)包
twine check dist/*
# 上傳到 TestPyPI(測試)
twine upload --repository testpypi dist/*
# 上傳到 PyPI(正式)
twine upload dist/*

最佳實(shí)踐與常見問題

最佳實(shí)踐

使用 src 布局

project/
├── src/
│   └── package_name/
├── tests/
└── pyproject.toml

優(yōu)點(diǎn):避免直接導(dǎo)入源碼目錄,確保測試的是安裝后的包。

版本號(hào)管理

  • 遵循語義化版本 (SemVer):主版本.次版本.修訂號(hào)
  • 考慮使用動(dòng)態(tài)版本或 bump2version 工具

依賴版本約束

  • 運(yùn)行依賴:使用寬松約束 >=1.0.0
  • 開發(fā)依賴:可以使用更嚴(yán)格約束

分離可選依賴

[project.optional-dependencies]
dev = ["pytest", "black"]
docs = ["sphinx"]

配置所有工具
將 black、ruff、pytest、mypy 等配置都放入 pyproject.toml

常見問題

Q1: 如何從 setup.py 遷移?

可以使用 ini2toml 工具自動(dòng)轉(zhuǎn)換:

pip install ini2toml[full]
ini2toml setup.cfg > pyproject.toml

Q2: 如何處理動(dòng)態(tài)內(nèi)容?

[project]
dynamic = ["version", "readme"]

[tool.setuptools.dynamic]
version = {attr = "mypackage.__version__"}
readme = {file = ["README.md", "CHANGELOG.md"]}

Q3: 如何添加數(shù)據(jù)文件?

[tool.setuptools.package-data]
mypackage = ["*.txt", "data/*.json"]

或使用 MANIFEST.in 文件。

Q4: 為什么安裝后找不到命令?

檢查以下幾點(diǎn):

  1. 虛擬環(huán)境是否激活
  2. [project.scripts] 配置是否正確
  3. 入口函數(shù)是否存在

Q5: 如何支持多個(gè) Python 版本?

requires-python = ">=3.8"

classifiers = [
    "Programming Language :: Python :: 3.8",
    "Programming Language :: Python :: 3.9",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11",
    "Programming Language :: Python :: 3.12",
]

總結(jié)

pyproject.toml 是現(xiàn)代 Python 項(xiàng)目的標(biāo)準(zhǔn)配置方式,它帶來了以下好處:

  1. 統(tǒng)一性:一個(gè)文件管理所有配置
  2. 可讀性:TOML 格式清晰易懂
  3. 安全性:聲明式配置,無代碼執(zhí)行
  4. 兼容性:所有現(xiàn)代工具都支持

通過本文的 PyImage Split 項(xiàng)目示例,我們?cè)敿?xì)介紹了:

  • [build-system]:構(gòu)建系統(tǒng)配置
  • [project]:項(xiàng)目元數(shù)據(jù)
  • [project.optional-dependencies]:可選依賴分組
  • [project.scripts]:命令行入口點(diǎn)
  • [tool.*]:各種開發(fā)工具配置

建議新項(xiàng)目直接使用 pyproject.toml,老項(xiàng)目也可以逐步遷移。這不僅能讓你的項(xiàng)目更加規(guī)范,也能更好地與 Python 生態(tài)系統(tǒng)中的各種工具協(xié)作。

本文以 PyImage Split 項(xiàng)目為例,該項(xiàng)目是一個(gè)使用 PySide6 構(gòu)建的圖片查看和拆分工具,完整代碼可在項(xiàng)目倉庫中查看。

以上就是使用pyproject.toml構(gòu)建現(xiàn)代化Python項(xiàng)目的詳細(xì)步驟的詳細(xì)內(nèi)容,更多關(guān)于pyproject.toml構(gòu)建Python項(xiàng)目的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • python清除字符串里非字母字符的方法

    python清除字符串里非字母字符的方法

    這篇文章主要介紹了python清除字符串里非字母字符的方法,涉及Python字符串正則替換操作的相關(guān)技巧,需要的朋友可以參考下
    2015-07-07
  • python獲取當(dāng)前時(shí)間對(duì)應(yīng)unix時(shí)間戳的方法

    python獲取當(dāng)前時(shí)間對(duì)應(yīng)unix時(shí)間戳的方法

    這篇文章主要介紹了python獲取當(dāng)前時(shí)間對(duì)應(yīng)unix時(shí)間戳的方法,涉及Python時(shí)間操作的相關(guān)技巧,非常簡單實(shí)用,需要的朋友可以參考下
    2015-05-05
  • python提取log文件內(nèi)容并畫出圖表

    python提取log文件內(nèi)容并畫出圖表

    這篇文章主要介紹了python提取log文件內(nèi)容并畫出圖表,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • 使用Selenium在Python中實(shí)現(xiàn)錄屏功能

    使用Selenium在Python中實(shí)現(xiàn)錄屏功能

    Selenium 是一個(gè)強(qiáng)大的用于自動(dòng)化測試的工具,但你知道它也可以用來錄制瀏覽器操作的視頻嗎?本文將介紹如何使用 Selenium 在 Python 中實(shí)現(xiàn)錄屏功能,以便記錄和分享你的網(wǎng)頁操作過程,需要的朋友可以參考下
    2023-11-11
  • 教你用Python腳本快速為iOS10生成圖標(biāo)和截屏

    教你用Python腳本快速為iOS10生成圖標(biāo)和截屏

    這篇文章主要介紹了教你用Python快速為iOS10生成圖標(biāo)和截屏的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-09-09
  • 在python中使用nohup命令說明

    在python中使用nohup命令說明

    這篇文章主要介紹了在python中使用nohup命令說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-04-04
  • PyTorch中 tensor.detach() 和 tensor.data 的區(qū)別解析

    PyTorch中 tensor.detach() 和 tensor.data 的

    這篇文章主要介紹了PyTorch中 tensor.detach() 和 tensor.data 的區(qū)別解析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-04-04
  • 利用Python找出序列中出現(xiàn)最多的元素示例代碼

    利用Python找出序列中出現(xiàn)最多的元素示例代碼

    這篇文章主要給大家介紹了關(guān)于利用Python找出序列中出現(xiàn)最多的元素的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-12-12
  • Python交換變量

    Python交換變量

    Python美味第一頓,來個(gè)方便快捷的變量交換!為什么是Python?!因?yàn)镻ython中交換變量不需要臨時(shí)變量!
    2008-09-09
  • 關(guān)于pygame自定義窗口創(chuàng)建及相關(guān)操作指南

    關(guān)于pygame自定義窗口創(chuàng)建及相關(guān)操作指南

    對(duì)于開發(fā)一個(gè)游戲來說,窗口的顯示肯定是前提中的前提,對(duì)于pygame來說,只需要一小段代碼就可以初始化窗口,下面這篇文章主要給大家介紹了關(guān)于pygame自定義窗口創(chuàng)建及相關(guān)操作的相關(guān)資料,需要的朋友可以參考下
    2022-07-07

最新評(píng)論

昌都县| 松原市| 炎陵县| 亚东县| 芮城县| 安多县| 湖口县| 邢台市| 桂阳县| 长岛县| 汕尾市| 武功县| 宣威市| 淳安县| 正定县| 北流市| 石楼县| 佛冈县| 平南县| 柳林县| 普陀区| 佳木斯市| 红原县| 富宁县| 文安县| 嘉荫县| 抚远县| 磴口县| 镶黄旗| 河津市| 芒康县| 江华| 石嘴山市| 岳普湖县| 嘉义市| 承德市| 宁城县| 乃东县| 庆城县| 镇康县| 定结县|