入口点规范

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

  • 发行版可以指定 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)
    

注意

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

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

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

文件格式

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

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

import configparser

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

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

配置文件的节表示入口点组,名称是名称,值编码对象引用和可选的额外功能。如果使用了额外功能,它们是方括号内的逗号分隔列表。

在一个值中,读取器必须接受并忽略冒号之前或之后、对象引用和左方括号之间、额外名称和分隔它们的方括号和冒号之间、以及右方括号之后的空格(包括多个连续空格)。额外功能的语法在 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 现有入口点功能(讨论)。