PEP 423 – 打包相关的命名规范和方案
- 作者:
- Benoit Bryon <benoit at marmelune.net>
- 讨论邮件列表:
- Distutils-SIG 邮件列表
- 状态:
- 已延期
- 类型:
- 信息性
- 主题:
- 打包
- 创建日期:
- 2012年5月24日
- 更新历史:
摘要
本文档涉及
- Python项目的名称,
- 要分发的Python包或模块的名称,
- 命名空间包。
它为发布者提供指导和方案
- 新项目应遵循以下指南。
- 现有项目应了解这些指南,并可以遵循针对现有项目的具体方案。
PEP延期
对该PEP的进一步考虑已被推迟,至少要等到PEP 426(包元数据2.0)和相关的更新解决之后。
术语
与其他PEP的关系
概述
以下总结了选择名称时应遵循的指南列表
- 了解并尊重命名空间所有权.
- 如果您的项目与其他项目或社区相关
- 在主项目的文档中搜索约定,因为项目应该组织社区贡献。
- 遵循特定项目或相关社区的约定(如果有)。
- 如果没有约定,遵循标准命名模式。
- 确保您的项目名称唯一,即避免重复
- 确保分发的包和模块名称唯一,除非您明确希望分发现有包或模块的替代方案。为包/模块名称和项目名称使用相同的值是实现此目的的推荐方法。
- 一次只分发一个包或模块,除非您知道自己在做什么。这使得可以应用“使用单个名称”规则,从而使名称保持一致。
- 使您的项目易于发现和记忆
- 避免嵌套过深。扁平化的东西比嵌套的东西更容易使用和记忆
- 建议使用一到两个命名空间级别,因为它们几乎总是足够。
- 即使不推荐,三个级别也是事实上的常见情况。
- 在大多数情况下,您不需要超过三个级别。
- 遵循PEP 8中关于包和模块名称的语法规范。
- 如果您遵循了特定的约定,或者您的项目旨在接收来自社区的贡献,组织社区贡献。
- 如有疑问,请咨询.
如有疑问,请咨询
如果您在阅读本文档后仍不确定,请在IRC或邮件列表上咨询Python社区。
顶级命名空间与代码所有权相关
这有助于避免项目名称之间的冲突。
所有权可以是
- 个人。例如:gp.fileupload由Gael Pasgrimaud拥有和维护。
- 组织。例如
- zest.releaser由Zest Software拥有和维护。
- Django由Django软件基金会拥有和维护。
- 小组或社区。例如:sphinx由Sphinx项目的开发者维护,而不仅仅是由其作者Georg Brandl维护。
- 与另一个包相关的小组或社区。例如:collective.recaptcha由其作者David Glick(Groundwire)拥有。但是,“collective”命名空间由Plone社区拥有。
尊重所有权
在使用命名空间之前,请了解其用途。
除非获得明确授权,否则不要插入您不拥有的命名空间。
例如,不要插入“django.contrib”命名空间,因为它由Django的核心贡献者管理。
项目作者可以定义例外情况。请参阅下面的组织社区贡献。
此外,此规则也适用于非Python项目。
例如,不要使用“apache”作为顶级命名空间:“Apache”是现有项目的名称(在“Apache”的情况下,它也是一个商标)。
私有(包括闭源)项目使用命名空间
…因为私有项目由某人拥有。因此,请应用所有权规则。
对于内部/客户项目,请使用您的公司名称作为命名空间。
此规则适用于闭源项目。
例如,如果您正在为“Python Sport”公司创建一个名为“climbing”的项目:请使用“pythonsport.climbing”名称,即使它是闭源的。
单个项目使用命名空间
…因为它们由个人拥有。因此,请应用所有权规则。
即使项目具有“内部”或“个人”名称,将其作为开源发布也并无不妥。
如果项目发展到作者希望更改所有权的程度(即项目不再属于个人),请记住重命名项目很容易。
社区拥有项目可以避免使用命名空间包
如果您的项目足够通用(即它不是对其他产品或框架的贡献),您可以避免使用命名空间包。基本条件通常是您的项目由一个专门负责此项目的团队(即开发团队)拥有。
只有当您确实打算将代码归社区所有时,才使用“共享”命名空间。
例如,sphinx项目属于Sphinx开发团队。无需在内部创建一个名为“sphinx”的命名空间包,其中只包含一个名为“sphinx.sphinx”的项目。
如有疑问,请使用个人/组织命名空间
如果您的项目确实是实验性的,最佳选择是使用个人或组织命名空间
- 它允许项目尽早发布。
- 如果项目被放弃,它不会阻塞名称。
- 它不会阻止将来的更改。当项目变得成熟并且没有理由保留个人所有权时,仍然可以重命名项目。
使用单个名称
每个项目只分发一个包(或一个模块),并使用包(或模块)名称作为项目名称。
- 它避免了项目名称和分发包或模块名称之间可能产生的混淆。
- 它使名称保持一致。
- 它很明确:当一个人看到项目名称时,他可以猜测包/模块名称,反之亦然。
- 它还限制了包/模块名称之间的隐式冲突。通过使用单个名称,当您将项目名称注册到PyPI时,您还执行了基本的包/模块名称可用性验证。
例如,pipeline、python-pipeline和django-pipeline都分发了一个名为“pipeline”的包或模块。因此,安装其中的两个会导致错误。如果这些发行版使用单个名称,则不会出现此问题。
是
- 包名:“kheops.pyramid”,即
import kheops.pyramid
- 项目名称:“kheops.pyramid”,即
pip install kheops.pyramid
否
- 包名:“kheops”
- 项目名称:“KheopsPyramid”
注意
由于历史原因,PyPI包含许多项目和分发包/模块名称不同的发行版。
多个包/模块应该很少见
从技术上讲,Python发行版可以提供多个包和/或模块。有关详细信息,请参阅安装脚本参考。
有些发行版确实如此。例如,setuptools和distribute都在除了各自的“setuptools”和“distribute”包之外,还声明了“pkg_resources”、“easy_install”和“site”模块。
将此用例视为例外情况。在大多数情况下,您不需要此功能。因此,分发应该一次只提供一个包或模块。
不同的名称应该很少见
对使用单个名称规则的一个显著例外是,当您明确需要不同的名称时。
例如,Pillow 项目提供了原始 PIL 分发的替代方案。这两个项目都分发了一个名为“PIL”的包。
将此用例视为例外情况。在大多数情况下,您不需要此功能。因此,分发包名称应等于项目名称。
遵循PEP 8中关于包和模块名称的语法规范
PEP 8 适用于 Python 包和模块的名称。
选择易记的名称
关于项目名称,有一点很重要,那就是它必须令人难忘。
例如,celery 不是一个有意义的名称。起初,并不明显它与消息队列有关。但它令人难忘,部分原因是它可以用来为 RabbitMQ 服务器提供数据。
选择有意义的名称
问问自己“我将如何用一句话描述这个名称的用途?”,然后“仅凭名称,是否有人能猜到它的用途?”。
例如,DateUtils 是一个有意义的名称。很明显,它与日期相关的实用程序有关。
当您使用命名空间时,请尝试使每个部分都具有意义。
使用打包元数据
将项目名称视为 PyPI 上的唯一标识符。
- 这些标识符必须保持人类可读性很重要。
- 如果这些标识符有意义则更好。
- 但标识符的主要目的不是对项目进行分类或描述。
分类器和关键词元数据用于对分发进行分类。摘要和描述元数据用于描述项目。
例如,有一个“Framework :: Twisted”分类器。即使名称非常异构(它们不遵循特定的模式),我们也能得到列表。
为了组织社区贡献,关于名称和命名空间的约定很重要,但关于元数据的约定应该更加重要。
例如,我们可以在许多地方找到 Plone 端口。
- plone.portlet.*
- collective.portlet.*
- collective.portlets.*
- collective.*.portlets
- 一些与供应商相关的项目,例如“quintagroup.portlet.cumulus”
- 甚至一些名称中没有出现“portlet”模式的项目。
即使 Plone 社区有约定,使用名称对分发进行分类也是不合适的。通过根据名称过滤,不可能获得提供 Plone 端口的所有分发的完整列表。但如果所有这些分发都使用“Framework :: Plone”分类器和“portlet”关键词,则可以实现。
避免嵌套过深
Python 之禅 说“扁平胜于嵌套”。
两级几乎总是足够
不要在深度嵌套的层次结构中定义所有内容:您最终会得到像“pythonsport.common.maps.forest”这样的项目和包。这种类型的名称既冗长又笨拙(例如,如果您从包中导入了许多内容)。
此外,随着不同包之间的界限变得模糊,大型层次结构往往会随着时间的推移而崩溃。
共识是,最好使用两级嵌套。
例如,我们有plone.principalsource
而不是 plone.source.principal
或类似的东西。名称更短,包结构更简单,并且在这里进行三级嵌套几乎没有什么好处。将所有“核心 Plone”源(源是一种词汇表)放入 plone.source.*
命名空间中是不切实际的,部分原因是一些源是其他包的一部分,部分原因是源已经存在于其他地方。如果我们创建了一个新的命名空间,它将从一开始就使用不一致。
是:“pyranha”
是:“pythonsport.climbing”
是:“pythonsport.forestmap”
否:“pythonsport.maps.forest”
只使用一级表示所有权
不要使用 3 个级别在社区命名空间中设置个人/组织所有权。
例如,让我们考虑一下
- 您正在连接到一个社区命名空间,例如“collective”。
- 并且您希望添加一个更严格的“所有权”级别,以避免在社区内部发生冲突。
在这种情况下,**最好将最严格的所有权级别用作第一级。**
例如,“collective”是“gergovie”所属的主要社区命名空间,“vercingetorix”是“gergovie”作者的名称。
否:“collective.vercingetorix.gergovie”
是:“vercingetorix.gergovie”
不要使用命名空间级别进行分类
改用使用打包元数据。
不要使用超过3级
从技术上讲,您可以创建深度嵌套的层次结构。但是,在大多数情况下,您不需要它。
注意
即使是命名空间标准化的社区,也不会使用超过 3 个级别。
在PyPI上注册名称
PyPI 是 Python 社区分发的中心位置。因此,它也是注册项目和包名称的地方。
有关详细信息,请参阅在软件包索引中注册。
方案
以下食谱将帮助您遵循上述指南和约定。
如何检查名称可用性?
在选择项目名称之前,请确保它尚未在以下位置注册
- PyPI
- 仅此而已。PyPI 是唯一官方场所。
例如,您还可以检查各种位置(例如流行的代码托管服务),但请记住,PyPI 是您在 Python 社区中**注册**名称的唯一场所。
这就是为什么您需要使用 PyPI 注册名称很重要的原因。
还要确保已分发包或模块的名称尚未注册
- 在Python 标准库中。
- 在
PyPI
中的项目内部。目前没有为此提供帮助程序。请注意,越多的项目遵循使用单个名称规则,验证就越容易。 - 如果您有任何疑问,可以咨询社区。
“使用单个名称”规则也有助于避免与包名称冲突:如果项目名称可用,那么包名称也很有可能可用。
如何重命名项目?
重命名项目是可能的,但请记住,这会导致一些混乱。因此,请特别注意 README 和文档,以便用户了解发生了什么。
- 首先,**不要从 PyPI 中删除旧版分发包**。因为一些用户可能正在使用它们。
- 复制旧项目,然后更改名称(项目和包/模块)。至少要注意以下方面:
- 打包文件,
- 包含源文件的文件夹名称,
- 文档,包括 README,
- 代码中的导入语句。
- 在 setup.cfg 文件中为新分发包分配
Obsoletes-Dist
元数据。请参阅 关于 Obsolete-Dist 的 PEP 345 和 setup.cfg 规范。 - 发布重命名项目的最新版本,然后发布它。
- 编辑旧项目
- 添加对新项目的依赖项,
- 删除除打包内容之外的所有内容,
- 在 setup 脚本中添加
Development Status :: 7 - Inactive
分类器, - 发布一个新版本。
因此,旧版包的用户
- 可以继续使用旧版分发包的已弃用版本,
- 可以升级到旧版分发包的最后一个版本,该版本为空…
- …并自动下载新分发包作为旧版分发包的依赖项。
发现旧项目的用户会看到它处于非活动状态。
改进PyPI上重命名项目的处理方式
如果许多项目遵循 重命名指南,那么许多旧版分发包将具有以下特征
Development Status :: 7 - Inactive
分类器。- 最新版本为空,除了打包内容。
- 最新版本“重定向”到另一个分发包。例如,它对重命名项目只有一个依赖项。
- 在较新的分发包中被引用为
Obsoletes-Dist
。
因此,将能够检测到重命名的项目并提高 PyPI 的可读性。以便用户可以专注于活动分发包。但是此功能现在不需要。没有紧急情况。本文档中不会介绍。
如何在现有项目上应用命名指南?
**现有项目没有义务重命名**。出于显而易见的原因,选择权留给项目作者和维护者。
但是,邀请项目作者
- 至少,说明当前命名。
- 然后计划和推广迁移。
- 可以选择实际重命名现有项目或分发的包/模块。
关于当前命名的说明
首先,重要的是您要说明当前的选择
- 问问自己“我为什么选择当前名称?”,然后记录下来。
- 如果与本文档中提供的指南存在差异,您应该告诉您的用户。
- 如果可能,至少为了记录在案,在项目的错误跟踪器中创建问题。然后您可以自由地稍后解决它们,或者可能将其标记为“wontfix”。
旨在接收社区贡献的项目也应该组织社区贡献。
推广迁移
每个 Python 开发人员都应该在可能的情况下迁移,或者在各自的社区中推广迁移。
在您的项目中应用这些指南,然后社区将看到它是安全的。
特别是,“领导者”(例如热门项目的作者)很有影响力,他们拥有权力,因此对社区负有责任。
在热门项目中应用这些指南,然后社区也将采用这些约定。
**项目在发布新(主要)版本时应推广迁移**,特别是如果此版本引入了对 Python 3.x、新的标准库打包或命名空间包的支持。
机会
随着 Python 3.3 的开发
- 许多项目与 Python 3.x 不兼容。这包括“大型”产品或框架。这意味着许多项目将不得不进行迁移以支持 Python 3.x。
- 打包(又名 distutils2)已准备就绪。发布后,将邀请项目迁移并使用新的打包方式。
- PEP 420 为 Python 带来了命名空间包的官方支持。
这意味着大多数活跃的项目都应该在明年(几年内)迁移以支持 Python 3.x、新的打包方式或新的命名空间包。
这样的机会是独一无二的,并且不会很快再次出现!因此,让我们尽快(即**现在**)引入和推广命名约定。
参考文献
其他背景资料
- Martin Aspeli 关于名称的文章。本文档的某些部分引用了这篇文章。
- 开发中的官方打包文档.
- 打包指南,其中有一个空的“命名规范”占位符。
参考文献和脚注
版权
本文档已进入公有领域。
来源:https://github.com/python/peps/blob/main/peps/pep-0423.rst
上次修改时间:2023-09-09 17:39:29 GMT