Python能做大项目(6)Poetry -- 项目管理的诗和远方之一

2023-12-25 23:04

本文主要是介绍Python能做大项目(6)Poetry -- 项目管理的诗和远方之一,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

[Poetry] 是一个依赖管理和打包工具。Poetry 的作者解释开发 Poetry 的初衷时说:

在这里插入图片描述

通过前面的案例,我们已经提出了一些问题。但不止于此。

当您将依赖加入到 requirements.txt 时,没有人帮你确定它是否与既存的依赖能够和平共处,这个过程要比我们想象的复杂许多,不仅仅是直接依赖,还需要考虑彼此的传递依赖是否也能彼此兼容;所以一般的做法是,先将它们加进来,完成开发和测试,在打包之前,运行pip freeze > requirements.txt来锁定依赖库的版本。但我们也在前面的案例中提到,这种方法可能会将不必要的开发依赖打入到发行版中;此外,它也会过度锁定版本,从而使得一些活跃的第三方库失去自动更新热修复和安全更新的机会。

项目的版本管理也是一个问题。在老旧的 Python 项目中,一般我们使用 bumpversion 来管理版本,它需要使用三个文件。在我的日常使用时,它常常会出现各种问题,最常见的是单双引号导致把__version__ = 0.1当成一个版本号,而不是0.1。这样打出来的包名也会奇怪地多一个无意义的 version 字样。单双引号则是因为你的 format 工具对字符串常量应该使用什么样的引号规则有自己的意见。

项目进行打包和发布需要准备太多的文件,正如 Poetry 的开发者所说,要确保这些文件的内容完全正确,对一个有经验的开发者来说,也不是轻而易举的事。

Poetry 解决了所有这些问题(除了案例中的第一个,该问题要通过 tox 和 CI 来解决)。它提供了版本管理、依赖解析、构建和发布的一站式服务,并将所有的配置,集中到一个文件中,即 pyproject.toml。此外,Poetry 还提供了一个简单的工程创建向导。不过这个向导的功能仍然过于简单,我们的推荐则是使用上一章介绍的 python project wizard。

在这里插入图片描述

现在,让我们看一眼 sample 项目中的 pyproject.toml 文件:

[tool]
[tool.poetry]
name = "sample"
version = "0.1.0"
homepage = "https://github.com/zillionare/sample"
description = "Skeleton project created by Python Project Wizard (ppw)."
authors = ["aaron yang <aaron_yang@jieyu.ai>"]
readme = "README.md"
license =  "MIT"
classifiers=['Development Status :: 2 - Pre-Alpha','Intended Audience :: Developers','License :: OSI Approved :: MIT License','Natural Language :: English','Programming Language :: Python :: 3','Programming Language :: Python :: 3.7','Programming Language :: Python :: 3.8','Programming Language :: Python :: 3.9','Programming Language :: Python :: 3.10',
]
packages = [{ include = "sample" },{ include = "tests", format = "sdist" },
][tool.poetry.dependencies]
python = ">=3.7.1,<4.0"
fire = "0.4.0"black  = { version = "^22.3.0", optional = true}
isort  = { version = "5.10.1", optional = true}
flake8  = { version = "4.0.1", optional = true}
flake8-docstrings = { version = "^1.6.0", optional = true }
pytest  = { version = "^7.0.1", optional = true}
pytest-cov  = { version = "^3.0.0", optional = true}
tox  = { version = "^3.24.5", optional = true}
virtualenv  = { version = "^20.13.1", optional = true}
pip  = { version = "^22.0.3", optional = true}
mkdocs  = { version = "^1.2.3", optional = true}
mkdocs-include-markdown-plugin  = { version = "^3.2.3", optional = true}
mkdocs-material  = { version = "^8.1.11", optional = true}
mkdocstrings  = { version = "^0.18.0", optional = true}
mkdocs-material-extensions  = { version = "^1.0.3", optional = true}
twine  = { version = "^3.8.0", optional = true}
mkdocs-autorefs = {version = "^0.3.1", optional = true}
pre-commit = {version = "^2.17.0", optional = true}
toml = {version = "^0.10.2", optional = true}
livereload = {version = "^2.6.3", optional = true}
pyreadline = {version = "^2.1", optional = true}
mike = { version="^1.1.2", optional=true}[tool.poetry.extras]
test = ["pytest","black","isort","flake8","flake8-docstrings","pytest-cov"]dev = ["tox", "pre-commit", "virtualenv", "pip", "twine", "toml"]doc = ["mkdocs","mkdocs-include-markdown-plugin","mkdocs-material","mkdocstrings","mkdocs-material-extension","mkdocs-autorefs","mike"][tool.poetry.scripts]
sample = 'sample.cli:main'[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"[tool.black]
line-length = 88
include = '\.pyi?$'
exclude = '''
/(\.eggs| \.git| \.hg| \.mypy_cache| \.tox| \.venv| _build| buck-out| build| dist
)/
'''
[tool.isort]
profile = "black"

我们简单地解读一下这个文件:
在 [tool.poetry] 那一节,定义了包的名字(这里是 sample)、版本号(这里是 0.1.0)和其它的一些字段,比如 classifiers,这是打包和发布时需要的。如果您熟悉 python setup tools,那么对这些字段将不会陌生。packages 字段指明了打包时需要包含的文件。在示例中,我们要求在以.whl 格式发布的包中,将 sample 目录下的所有文件打包发布;而以 sdist 格式(即.tar.gz) 发布的包中,还要包含 tests 目录下的文件。

接下来是 [tool.poetry.dependencies] 一节,这是我们声明项目依赖的地方。首先是项目要求的 python 版本声明。这里我们要求必须在 3.7.1 以上,4.0 以下的 python 环境中运行。因此,python 3.7.1,3.8, 3.9, 3.10 都是恰当的 python 版本,但 4.0 则不允许。

接下来就是工程中需要用到的其它第三方依赖,有运行时的(即当最终用户使用我们的程序时,必须安装的那些第三方依赖),也有开发时的(即只在开发和测试过程中使用到的,比如文档工具类 mkdocs,测试类 tox, pytest 等)。

我们对运行时和开发时需要的依赖进行了分组。对开发时需要的依赖,我们分成 dev, test 和 doc 三组,通过 [tool.poetry.extras] 中进行分组声明。对于归入到 dev, test 和 doc 分组中的依赖,我们在 [tool.poetry.dependencies] 中,将其声明为 optional 的,这样在安装最终分发包时,这些声明为 optional 的第三方依赖将不会安装到用户环境中。

再接下来,[tool.poetry.scripts] 声明了一个 console script 入口。Console script 是一种特殊的 Python 脚本,它使得您可以象调用普通的 shell 命令一样来调用这个脚本。

[tool.poetry.scripts]
sample = 'sample.cli:main'

在这里插入图片描述

当 sample 包被安装后,就往安装环境里注入了一个名为sample的shell 命令。它可以接受各种参数,最终将交给 sample\cli.py 中的 main 函数来执行。

接下来就是关于如何构建的相关指示,在 [build-system] 中。如果你的程序中只包含纯粹的 Python 代码,那么这部分可不做任何修改。如果你的程序包含了一些原生的代码(比如 c 的),那么就需要自己定义构建脚本。

在示例代码中,还有 [tool.black] 和 [tool.isort] 两个小节,分别是 black(代码格式化工具)和 isort(将导入进行排序的工具)的配置文件。它们是对 pyproject.toml 的扩展,并不是 poetry 所要求的。

版本管理

poetry 为我们的 package 提供了基于语义 (semantic version) 的版本管理功能。它通过poetry version这个命令,让我们查看 package 的版本,并且实现版本号的升级。

假设您已经使用 [python project wizard] 生成了一个工程框架,那么应该可以在根目录下找到 pyproject.toml 文件,其中有一项:

version = 0.1

如果您现在运行poetry version这个命令,就会显示0.1这个版本号。

Poetry 使用基于语义的版本 (semantic version) 表示法。

在 Poetry 中,当我们需要修改版本号时,并不是直接指定新的版本号,而是通过poetry version semver来修改版本。semver可以是patch, minor, major, prepatch, preminor, premajorprerelease中的一个。这些关键字定义在规范 PEP 440 中。

semver与您当前的版本号相结合,通过运算,就得出了新的版本号:

rulebeforeafter
major1.3.02.0.0
minor2.1.42.2.0
patch4.1.14.1.2
premajor1.0.22.0.0-alpha.0
preminor1.0.21.1.0-alpha.0
prepatch1.0.21.0.3-alpha.0
prerelease1.0.21.0.3-alpha.0
prerelease1.0.3-alpha.01.0.3-alpha.1
prerelease1.0.3-beta.01.0.3-beta.1

可以看出,poetry 对版本号的管理是完全符合 semantic version 的要求的。当你完成了一个小的修订(比如修复了一个 bug,或者增强了性能,或者修复了安全漏洞),此时只应该递增 package 的修订号,即 x.y.z 中的’z’,这时我们就应该使用命令:

$ poetry version patch

如果之前的版本是 0.1.0,那么运行上述命令后,版本号将变更为 0.1.1。
如果我们的 package 新增加了一些功能,而之前提供的功能(API)都还能不加修改,继续使用,那么我们应该递增次版本号,即 x.y.z 中的’y’。这时我们应该使用命令:

$ poetry version minor

如果之前的版本是 0.1.1,那么运行上述命令后,版本号将变更为 0.2.0

如果我们的 package 进行了大幅的修改,并且之前提供的功能(API)的签名已经变掉,从而使得调用者必须修改他们的程序才能继续使用这些 API,又或者新的版本不再能兼容老版本的数据格式,用户必须对数据进行额外的迁移,那么,我们就认为这是一次破坏性的更新,必须升级主版本号:

$ poetry version major

如果之前的版本号是 0.3.1, 那么运行上述命令之后,版本号将变更为 1.0.0;如果之前的版本号是 1.2.1,那么运行上述命令之后,版本号将变更为 2.0.0。

除此之外,poetry 还提供了预发布版本号的支持。比如,上一个发布的版本是 0.1.0,那么我们在正式发布 0.1.1 这个修订之前,可以使用 0.1.1.a0 这个版本号:

$ poetry version prerelease
Bumping version from 0.1.0 to 0.1.1a0

如果需要再出一个 alpha 版本,则可以再次运行上述命令:

$ poetry version prerelease
Bumping version from 0.1.1a0 to 0.1.1a1

如果 alpha 版本已经完成,可以正式发布,运行下面的命令:

$ poetry version patch
Bumping version from 0.1.1a1 to 0.1.1

poetry 暂时还没有提供从 alpha 转到 beta 版本系列的命令。如果有此需要,您需要手工编辑 pyproject.toml 文件。

除了 poetry version prerelease 之外,我们还注意到上面列出的 premajor, preminor 和 prepatch 选项。它们的作用也是将版本号修改为 alpha 版本系列,但无论你运行多少次,它们并不会象 prerelease 选项一样,递增 alpha 版本号。所以在实际的 alpha 版本管理中,似乎只使用poetry version prerelease就可以了。


本文来源于《Python能做大项目》(暂定名),将由机械工业出版社出版。全书已经在大富翁量化官网上首发,欢迎提前阅读。


【本系列其它文章】

Python能做大项目(1) - 为什么要学Python之一
Python能做大项目(2) - 开发环境构建
Python能做大项目(3) - 依赖地狱与Conda虚拟环境
Python能做大项目(4) - 项目布局与生成向导
Python能做大项目(5) - 基于语义的版本管理
Python能做大项目(6) - Poetry: 项目管理的诗和远方之一

这篇关于Python能做大项目(6)Poetry -- 项目管理的诗和远方之一的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/537278

相关文章

Python实现网格交易策略的过程

《Python实现网格交易策略的过程》本文讲解Python网格交易策略,利用ccxt获取加密货币数据及backtrader回测,通过设定网格节点,低买高卖获利,适合震荡行情,下面跟我一起看看我们的第一... 网格交易是一种经典的量化交易策略,其核心思想是在价格上下预设多个“网格”,当价格触发特定网格时执行买

Python标准库之数据压缩和存档的应用详解

《Python标准库之数据压缩和存档的应用详解》在数据处理与存储领域,压缩和存档是提升效率的关键技术,Python标准库提供了一套完整的工具链,下面小编就来和大家简单介绍一下吧... 目录一、核心模块架构与设计哲学二、关键模块深度解析1.tarfile:专业级归档工具2.zipfile:跨平台归档首选3.

使用Python构建智能BAT文件生成器的完美解决方案

《使用Python构建智能BAT文件生成器的完美解决方案》这篇文章主要为大家详细介绍了如何使用wxPython构建一个智能的BAT文件生成器,它不仅能够为Python脚本生成启动脚本,还提供了完整的文... 目录引言运行效果图项目背景与需求分析核心需求技术选型核心功能实现1. 数据库设计2. 界面布局设计3

Python进行JSON和Excel文件转换处理指南

《Python进行JSON和Excel文件转换处理指南》在数据交换与系统集成中,JSON与Excel是两种极为常见的数据格式,本文将介绍如何使用Python实现将JSON转换为格式化的Excel文件,... 目录将 jsON 导入为格式化 Excel将 Excel 导出为结构化 JSON处理嵌套 JSON:

Python操作PDF文档的主流库使用指南

《Python操作PDF文档的主流库使用指南》PDF因其跨平台、格式固定的特性成为文档交换的标准,然而,由于其复杂的内部结构,程序化操作PDF一直是个挑战,本文主要为大家整理了Python操作PD... 目录一、 基础操作1.PyPDF2 (及其继任者 pypdf)2.PyMuPDF / fitz3.Fre

python设置环境变量路径实现过程

《python设置环境变量路径实现过程》本文介绍设置Python路径的多种方法:临时设置(Windows用`set`,Linux/macOS用`export`)、永久设置(系统属性或shell配置文件... 目录设置python路径的方法临时设置环境变量(适用于当前会话)永久设置环境变量(Windows系统

python中列表应用和扩展性实用详解

《python中列表应用和扩展性实用详解》文章介绍了Python列表的核心特性:有序数据集合,用[]定义,元素类型可不同,支持迭代、循环、切片,可执行增删改查、排序、推导式及嵌套操作,是常用的数据处理... 目录1、列表定义2、格式3、列表是可迭代对象4、列表的常见操作总结1、列表定义是处理一组有序项目的

python运用requests模拟浏览器发送请求过程

《python运用requests模拟浏览器发送请求过程》模拟浏览器请求可选用requests处理静态内容,selenium应对动态页面,playwright支持高级自动化,设置代理和超时参数,根据需... 目录使用requests库模拟浏览器请求使用selenium自动化浏览器操作使用playwright

python使用try函数详解

《python使用try函数详解》Pythontry语句用于异常处理,支持捕获特定/多种异常、else/final子句确保资源释放,结合with语句自动清理,可自定义异常及嵌套结构,灵活应对错误场景... 目录try 函数的基本语法捕获特定异常捕获多个异常使用 else 子句使用 finally 子句捕获所

Python极速搭建局域网文件共享服务器完整指南

《Python极速搭建局域网文件共享服务器完整指南》在办公室或家庭局域网中快速共享文件时,许多人会选择第三方工具或云存储服务,但这些方案往往存在隐私泄露风险或需要复杂配置,下面我们就来看看如何使用Py... 目录一、android基础版:HTTP文件共享的魔法命令1. 一行代码启动HTTP服务器2. 关键参