分发包与导入包#
人们通常用“包”一词来指代许多不同的概念。本页面阐明了 Python 打包中两个不同但相关的含义,“分发包”和“导入包”之间的差异。
什么是分发包?#
分发包是可以安装的一段软件。大多数情况下,这与“项目”同义。当您键入 pip install pkg
,或在 pyproject.toml
中编写 dependencies = ["pkg"]
时,pkg
是分发包的名称。当您搜索或浏览 PyPI(安装 Python 库和工具最广为人知的集中式来源)时,您看到的是分发包列表。或者,术语“分发包”可以用来指代包含项目特定版本的文件。
请注意,在 Linux 世界中,“分发包”,最常见的缩写为“distro 包”或简称“包”,是由 Linux 发行版 的系统包管理器提供的,这是不同的含义。
什么是导入包?#
导入包是 Python 模块。因此,当您在 Python 代码中编写 import pkg
或 from pkg import func
时,pkg
是导入包的名称。更准确地说,导入包是可以包含子模块的特殊 Python 模块。例如,numpy
包包含 numpy.linalg
和 numpy.fft
等模块。通常,导入包是文件系统上的一个目录,其中包含 .py
文件形式的模块和子目录形式的子包。
一旦您安装了提供导入包的分发包,您就可以使用该导入包。
分发包和导入包之间的联系是什么?#
大多数情况下,分发包提供一个具有匹配名称的导入包(或非包模块)。例如,pip install numpy
允许您 import numpy
。
但是,这只是一个约定。PyPI 和其他包索引不会强制执行分发包的名称与其提供的导入包之间的任何关系。(由此产生的一个后果是,如果您看到 import foo
,您不能盲目安装 PyPI 包 foo
;这可能会安装一个意外的,甚至可能是恶意的包。)
一个发行包可以提供一个具有不同名称的导入包。一个例子是用于图像处理的流行的 Pillow 库。它的发行包名称是 Pillow
,但它提供的导入包是 PIL
。这是由于历史原因:Pillow 最初是 PIL 库的一个分支,因此它保留了导入名称 PIL
,这样现有的 PIL 用户可以毫不费力地切换到 Pillow。更一般地说,现有库的分支是发行包和导入包名称不同的常见原因。
在给定的包索引(如 PyPI)中,发行包名称必须唯一。另一方面,导入包没有这样的要求。具有相同名称的导入包可以由多个发行包提供。同样,分支是这种情况的常见原因。
相反,一个发行包可以提供多个导入包,尽管这种情况不常见。一个例子是 attrs 发行包,它同时提供了具有较新 API 的 attrs
导入包,以及具有较旧但受支持的 API 的 attr
导入包。
发行包名称和导入包名称如何比较?#
导入包的名称应该是有效的 Python 标识符(确切规则可以在 Python 文档中找到)[1]。特别是,它们使用下划线 _
作为单词分隔符,并且区分大小写。
另一方面,发行包可以使用连字符 -
或下划线 _
。它们还可以包含点 .
,有时用于打包 命名空间包 的子包。对于大多数目的,它们不区分大小写,也不区分 -
和 _
的差异,例如,pip install Awesome_Package
与 pip install awesome-package
相同(确切的规则在 名称规范说明 中给出)。