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: 项目管理的诗和远方之一

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/270161.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023读书笔记57|《顾城诗选》——我们走进了夜海, 去打捞遗失的繁星

2023读书笔记57|《顾城诗选》——我们走进了夜海&#xff0c; 去打捞遗失的繁星 细雨&#xff0c;洗去空气中的浮尘&#xff0c; 薄暗里蜜酒散开阵阵醇香。 野蜂在风雨的摇荡中开始安眠&#xff0c; 带着无限甜美的梦想。 河岸边&#xff0c;开满了耀眼的冰花。 沙洲上&#x…

设计模式-生成器模式

设计模式专栏 模式介绍模式特点应用场景生成器模式和工厂模式的区别代码示例Java实现生成器模式Python实现生成器模式 生成器模式在spring中的应用 模式介绍 生成器模式是一种创建型模式&#xff0c;它的主要目的是将一个复杂对象的构建与它的表示分离&#xff0c;使得同样的构…

OCP NVME SSD规范解读-1

OCP&#xff08;Open Compute Project&#xff09;是一个由Facebook于2011年发起的开源项目。其目标是重新设计和优化数据中心的硬件&#xff0c;包括服务器、存储、网络设备等&#xff0c;以提高效率&#xff0c;降低运营成本&#xff0c;并推动技术的创新和标准化。 在OCP中&…

thinkphp6.0的workerman在PHP8.0下报错

一、我先升级了thinkphp6.0到最新版本&#xff1a; composer update topthink/framework二、结果提示我composer版本过低&#xff0c;需要升级到2&#xff0c;于是我又升级了composer composer self-update 三、我又升级了workerman: composer require topthink/think-work…

主机安全技术措施

目录 身份鉴别 进阶 访问控制 进阶 安全审计 进阶 ​编辑 剩余信息保护 入侵防范 进阶 恶意代码防范 资源控制 身份鉴别 进阶 访问控制 进阶 安全审计 进阶 剩余信息保护 入侵防范 进阶 恶意代码防范 资源控制 ~over~

【回溯】符号三角形问题Python实现

文章目录 [toc]问题描述回溯法时间复杂性Python实现 个人主页&#xff1a;丷从心 系列专栏&#xff1a;回溯法 问题描述 下图是由 14 14 14个“ ”和 14 14 14个“ − - −”组成的符号三角形&#xff0c; 2 2 2个同号下面都是” “&#xff0c; 2 2 2个异号下面都是“ −…

如何编写高效清晰的嵌入式C程序

作为嵌入式工程师&#xff0c;怎么写出效率高、思路清晰的C语言程序呢? 要用C语言的思维方式来进行程序的构架构建 要有良好的C语言算法基础&#xff0c;以此来实现程序的逻辑构架 灵活运用C语言的指针操作 虽然看起来以上的说法很抽象&#xff0c;给人如坠雾里的感觉&…

智能优化算法应用:基于厨师算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于厨师算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于厨师算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.厨师算法4.实验参数设定5.算法结果6.参考文献7.MA…

reactive和TypeScript标注数据类型-ts使用方法

一、vite项目中<script setup lang"ts"> : lang"ts" 是表明支持ts校验&#xff08;ts 全称typescript,是es6语法&#xff0c;是javascript的超集强类型编程语言&#xff0c;类似java&#xff0c;定义变量类型后&#xff0c;赋值类型不一致&#xff0…

网站管理员应该知道的:一款免费、简单、强大的 WAF(雷池社区版)

作为网站管理员&#xff0c;一定会关注网站是否安全&#xff0c;是否能够抵御黑客的攻击&#xff0c;是否能够保护数据和用户。可能已经听说过 WAF&#xff08;Web Application Firewall&#xff0c;Web 应用防火墙&#xff09;&#xff0c;一种能够在应用层对 Web 流量进行检测…

图灵日记之java奇妙历险记--输入输出方法数组

目录 输入输出输出到控制台从键盘输入使用 Scanner 读取字符串/整数/浮点数使用 Scanner 循环读取 猜数字方法方法定义方法调用的执行过程实参和形参的关系(重要)方法重载 数组数组的创建数组的初始化动态初始化静态初始化 数组的使用元素访问遍历数组 数组是引用类型null数组应…

大创项目推荐 深度学习OCR中文识别 - opencv python

文章目录 0 前言1 课题背景2 实现效果3 文本区域检测网络-CTPN4 文本识别网络-CRNN5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习OCR中文识别系统 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;…

SQL实践篇(三):什么是Redis

文章目录 简介Redis是什么&#xff0c;为什么这么快&#xff1f;Redis的数据类型字符串Hash字符串列表字符串集合有序字符串集合其他数据类型 总结参考文献 简介 Redis是一种基于内存的键值数据库&#xff0c;键值数据库会使用哈希表存储key和value。其中key和value可以是任何…

【力扣】199.二叉树的右视图

看到这个题目的一瞬间&#xff0c;我想递归&#xff0c;必须用递归。最近被递归折磨的有点狠&#xff0c;但是我感觉我快要打败它了&#xff0c;就是现在稍稍有点处于劣势。不过没关系&#xff0c;来日方长不是。 法一&#xff1a;递归 题解&#xff1a; 之前想的就是先递归&…

python:改进型鳟海鞘算法(SSALEO)求解23个基本函数

一、改进型鳟海鞘算法SSALEO 改进型鳟海鞘算法&#xff08;SSALEO&#xff09;由Mohammed Qaraad等人于2022年提出。 参考文献&#xff1a;M. Qaraad, S. Amjad, N. K. Hussein, S. Mirjalili, N. B. Halima and M. A. Elhosseini, "Comparing SSALEO as a Scalable Larg…

50个免费的 AI 工具,提升工作效率(附网址)

上次我们已经介绍了20个精选的提高工作效率的免费AI工具&#xff0c;但如果你觉得这些AI工具还不过瘾的话&#xff0c;想进一步成为职场中最了解AI的人&#xff0c;本文将汇总介绍免费最新的50个AI工具。 DeepSwap DeepSwap 是一个基于 AI 的工具&#xff0c;适用于想要制作令人…

Kafka生产环境问题总结与性能优化实践

Kafka可视化管理工具kafka-manager 安装及基本使用可参考: httos://wwwcnbloas.com/dadonaaa/o/8205302.html 线上环境规划 1. 消息丢失情况: 消

【MATLAB库函数系列】线性调频Z(Chirp-Z,CZT)的MATLAB源码和C语言实现

在上一篇博客 【数字信号处理】线性调频Z(Chirp-Z,CZT)算法详解 已经详细介绍了CZT变换的应用背景和原理,先回顾一下: 回顾CZT算法 采用 FFT 算法可以很快计算出全部 N N N点 DFT 值,即Z变换 X ( z ) X(z) <

LaTex插入图片、插入表格、插入公式

目录 一、插入图片 1&#xff09;改变图片的大小、旋转图片 2&#xff09;标签和交叉引用 3&#xff09;插入单排多图无小标题共享大标题 4&#xff09;单排变多排 5&#xff09;图片的位置 6&#xff09;图片横跨双栏 二、插入表格 1&#xff09;合并单元格 2&#…

RHCE9学习指南 第9章 权限管理

9.1 所有者所属组 为了了解所有者和所属组的概念&#xff0c;我们先看图9-1。 图9-1 用房子来帮助理解所有者和所属组 张老板是公司老板&#xff0c;买了一套房作为员工宿舍给A部门的员工居住。张老板是房主&#xff0c;所以他对房子具有很多权限&#xff0c;A部门员工只能具…