入口点规范#

入口点是一种机制,用于已安装的分发来宣传其提供的组件,以便其他代码发现和使用。例如

  • 分发可以指定 console_scripts 入口点,每个入口点都引用一个函数。当 pip(或另一个支持 console_scripts 的安装程序)安装分发时,它将为每个入口点创建一个命令行包装器。

  • 应用程序可以使用入口点加载插件;例如,Pygments(一种语法高亮工具)可以使用单独安装的包中的其他词法分析器和样式。有关此内容的更多信息,请参阅 创建和发现插件

入口点文件格式最初开发是为了允许使用 setuptools 构建的包提供集成点元数据,这些元数据将在运行时使用 importlib.metadata 读取。现在,它被定义为 PyPA 互操作性规范,以便允许 setuptools 以外的构建工具发布 importlib.metadata 兼容的入口点元数据,以及 importlib.metadata 以外的运行时库以可移植的方式读取已发布的入口点元数据(可能采用不同的缓存和冲突解决策略)。

数据模型#

从概念上讲,入口点由三个必需属性定义

  • 入口点所属的指示它提供的对象类型。例如,组 console_scripts 用于引用可作为命令使用的函数的入口点,而 pygments.styles 是用于定义 pygments 样式的类的组。使用者通常定义预期接口。为了避免冲突,定义新组的使用者应使用以使用者项目拥有的 PyPI 名称开头的名称,后跟 .。组名必须是一组或多组字母、数字和下划线,用点分隔(正则表达式 ^\w+(\.\w+)*$)。

  • 名称在其组中标识此入口点。此名称的具体含义取决于使用者。对于控制台脚本,入口点的名称是用于启动它的命令。在一个分发中,入口点名称应该是唯一的。如果不同的分发提供了相同的名称,则使用者决定如何处理此类冲突。名称可以包含 = 以外的任何字符,但不能以任何空白字符开头或结尾,也不能以 [ 开头。对于新入口点,建议仅使用字母、数字、下划线、点和破折号(正则表达式 [\w.-]+)。

  • 对象引用指向 Python 对象。它采用 importable.moduleimportable.module:object.attr 形式。用点号和冒号分隔的每个部分都是有效的 Python 标识符。它的查找方式如下

    import importlib
    modname, qualname_separator, qualname = object_ref.partition(':')
    obj = importlib.import_module(modname)
    if qualname_separator:
        for attr in qualname.split('.'):
            obj = getattr(obj, attr)
    

注意

某些工具将这种对象引用本身称为“入口点”,因为没有更好的术语,尤其是在它指向用于启动程序的函数时。

还有一个可选属性:extras 是一个字符串集,用于标识提供入口点的发行版的可选功能。如果指定了这些功能,则入口点需要这些“extras”的依赖项。请参阅元数据字段 Provides-Extra(多次使用)

不再建议为入口点使用 extras。使用者应支持从现有发行版中解析它们,但随后可以忽略它们。新的发布工具无需支持指定 extras。处理 extras 的功能与 setuptools 管理“egg”包的模型相关,但 pip 和 virtualenv 等较新的工具使用不同的模型。

文件格式#

入口点在发行版的 *.dist-info 目录中的名为 entry_points.txt 的文件中定义。这是在 记录已安装的项目 中针对已安装的发行版,以及在 二进制发行版格式 中针对轮子描述的目录。该文件使用 UTF-8 字符编码。

文件内容采用 INI 格式,由 Python 的 configparser 模块读取。但是,configparser 默认将名称视为不区分大小写,而入口点名称区分大小写。区分大小写的配置解析器可以这样创建

import configparser

class CaseSensitiveConfigParser(configparser.ConfigParser):
    optionxform = staticmethod(str)

入口点文件必须始终使用 = 来分隔名称和值(而 configparser 也允许使用 :)。

配置文件的部分表示入口点组,名称是名称,值对对象引用和可选 extras 进行编码。如果使用 extras,它们是方括号内的逗号分隔列表。

在值中,读者必须接受并忽略在冒号之前或之后、在对象引用和左方括号之间、在 extra 名称和分隔它们的方括号和冒号之间以及在右方括号之后出现的空格(包括连续的多个空格)。extras 的语法在 PEP 508(作为 extras)中作为一部分正式指定,并且在 PEP 685 中指定的值的限制。对于编写文件的工具,建议仅在对象引用和左方括号之间插入空格。

例如

[console_scripts]
foo = foomod:main
# One which depends on extras:
foobar = foomod:main_bar [bar,baz]

# pytest plugins refer to a module, so there is no ':obj'
[pytest11]
nbval = nbval.plugin

用于脚本#

在打包中,两组入口点具有特殊意义:console_scriptsgui_scripts。在这两组中,入口点的名称应可在安装包后在系统 shell 中用作命令。对象引用指向一个函数,该函数将在运行此命令时被调用,且不带任何参数。该函数可以返回一个整数用作进程退出代码,而返回 None 等同于返回 0

例如,入口点 mycmd = mymod:main 将创建一个命令 mycmd,启动类似这样的脚本

import sys
from mymod import main
sys.exit(main())

console_scriptsgui_scripts 之间的区别仅影响 Windows 系统。 console_scripts 封装在控制台可执行文件中,因此它们附加到控制台并可以使用 sys.stdinsys.stdoutsys.stderr 进行输入和输出。 gui_scripts 封装在 GUI 可执行文件中,因此它们可以在没有控制台的情况下启动,但不能使用标准流,除非应用程序代码将它们重定向。其他平台没有同样的区别。

安装工具应在安装方案的脚本目录中为 console_scriptsgui_scripts 设置包装器。它们不必将此目录放入 PATH 环境变量中,该变量定义了在何处找到命令行工具。

由于文件是从名称创建的,并且某些文件系统不区分大小写,因此软件包应避免在这些组中使用仅大小写不同的名称。当名称仅在大小写上有所不同时,安装工具的行为是未定义的。

历史记录#

  • 2017 年 10 月:此规范旨在将 setuptools 的现有入口点特性形式化(讨论)。