Following system colour scheme - Python 增强提案 Selected dark colour scheme - Python 增强提案 Selected light colour scheme - Python 增强提案

Python 增强提案

PEP 423 – 与打包相关的命名约定和方法

作者:
Benoit Bryon <benoit at marmelune.net>
讨论至:
Distutils-SIG 邮件列表
状态:
推迟
类型:
信息性
主题:
打包
创建日期:
2012年5月24日
发布历史:


目录

摘要

本文档涉及

  • Python项目名称,
  • 正在分发的Python包或模块名称,
  • 命名空间包。

它为分发作者提供了指南和方法

PEP 延期

本PEP的进一步审议已被推迟,至少要等到 PEP 426(软件包元数据2.0)及相关更新解决之后。

术语

参考是Python文档中的打包术语

与其他 PEP 的关系

  • PEP 8 处理代码风格指南,包括Python包和模块的名称。它涵盖了包/模块名称的语法。
  • PEP 345 处理打包元数据,并定义了 packaging.core.setup() 函数的名称参数。
  • PEP 420 处理命名空间包。它为Python核心带来了命名空间包的支持。在此之前,命名空间包是由外部库实现的。
  • PEP 3108 处理应用于标准库的Python 2.x和Python 3.x之间的过渡:一些模块将被删除,一些将被重命名。它指出命名约定很重要,并且是一个过渡计划的例子。

概述

以下是选择名称时应遵循的指南摘要列表

如有疑问,请咨询

如果您阅读本文档后仍感到不确定,请在IRC或邮件列表上咨询Python社区

顶级命名空间与代码所有权相关

这有助于避免项目名称之间的冲突。

所有权可以是

  • 个人。示例:gp.fileupload 由Gael Pasgrimaud拥有和维护。
  • 组织。示例
    • zest.releaser 由Zest Software拥有和维护。
    • Django 由Django Software Foundation拥有和维护。
  • 一个团体或社区。示例: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上注册项目名称时,您也执行了基本的包/模块名称可用性验证。

    例如,pipelinepython-pipelinedjango-pipeline 都分发了一个名为“pipeline”的包或模块。因此,安装其中两个会导致错误。如果这些分发使用单一名称,则不会发生此问题。

  • 包名称:“kheops.pyramid”,即 import kheops.pyramid
  • 项目名称:“kheops.pyramid”,即 pip install kheops.pyramid

  • 包名称:“kheops”
  • 项目名称:“KheopsPyramid”

注意

由于历史原因,PyPI 包含许多项目和分发包/模块名称不同的分发。

多个包/模块应该很少见

从技术上讲,Python 分发可以提供多个包和/或模块。有关详细信息,请参阅安装脚本参考

有些分发确实如此。例如,setuptoolsdistribute 都声明了“pkg_resources”、“easy_install”和“site”模块,此外还有各自的“setuptools”和“distribute”包。

将此用例视为例外。在大多数情况下,您不需要此功能。因此,一个分发应该一次只提供一个包或模块。

不同的名称应该很少见

使用单一名称规则的一个显著例外是当您明确需要不同名称时。

例如,Pillow 项目提供了原始 PIL 分发的替代方案。这两个项目都分发一个“PIL”包。

将此用例视为例外。在大多数情况下,您不需要此功能。因此,分发包名称应与项目名称相同。

遵循PEP 8中包和模块名称的语法

PEP 8 适用于 Python 包和模块的名称。

如果您使用单一名称,那么 PEP 8 也适用于项目名称。例外情况是命名空间包,项目名称中需要点。

选择令人难忘的名称

项目名称的一件重要事情是它要令人难忘。

例如,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上注册名称很重要的原因。

还要确保已分发包或模块的名称尚未注册

使用单一名称规则也有助于您避免与包名称冲突:如果项目名称可用,那么包名称也很可能可用。

如何重命名项目?

重命名项目是可能的,但请记住这会造成一些混淆。因此,请特别注意 README 和文档,以便用户理解发生了什么。

  1. 首先,不要从 PyPI 中删除旧的分发。因为有些用户可能正在使用它们。
  2. 复制旧项目,然后更改名称(项目和包/模块)。至少要注意
    • 打包文件,
    • 包含源文件的文件夹名称,
    • 文档,包括 README,
    • 代码中的导入语句。
  3. 在 setup.cfg 文件中为新分发分配 Obsoletes-Dist 元数据。请参阅 PEP 345 关于 Obsolete-Distsetup.cfg 规范
  4. 发布重命名项目的新版本,然后发布它。
  5. 编辑旧项目
    • 添加对新项目的依赖,
    • 删除除打包内容之外的所有内容,
    • 在安装脚本中添加 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、新打包或新命名空间包。

这样的机会是独一无二的,不会很快再次出现!所以让我们尽快(即现在)引入和推广命名约定。

参考资料

额外背景

参考文献和脚注


来源:https://github.com/python/peps/blob/main/peps/pep-0423.rst

最后修改:2025-05-03 18:09:21 GMT