要在 macOS 上为使用 src 布局的 Python 项目配置包发现,请在 pyproject.toml 中将 setuptools 指向 src,然后仅在需要控制发布哪些包时设置包名筛选器。对于常规项目,setuptools 通常可以自动检测该布局;当您希望包含或排除的内容可预测时,显式发现设置会非常有用。这些说明适用于 setuptools,并不适用于所有 Python 构建后端。
检查项目结构和构建后端
在“终端”中,切换到项目根目录(即包含 pyproject.toml 的文件夹),并使用 macOS 的默认 shell (zsh) 或已配置的 bash 检查文件:
cd '/path/to/project'
find src -maxdepth 3 -type f -print
将带引号的路径替换为实际的项目位置。单引号可防止路径中的空格和 shell 元字符被解析。典型的包可能位于 src/my_package/__init__.py,其下方的目录中包含子包。导入名称为 my_package;名为 src 的目录仅作为容器,并不是该名称的一部分。
检查 pyproject.toml 是否在 [build-system] 下选择了 setuptools,例如包含 requires = ["setuptools>=61"] 和 build-backend = "setuptools.build_meta"。setuptools 文档说明,当未显式提供包和模块列表时,它会对包括 src 在内的常见布局进行自动发现。其他后端有各自的配置,因此切勿将 setuptools 设置复制到其他后端的配置表中。Setuptools: 使用 pyproject.toml 文件配置 setuptools
在 pyproject.toml 中配置显式发现
如果您希望明确将发现根目录设为 src,请将以下 setuptools 配置添加到现有文件中:
[tool.setuptools.packages.find]
where = ["src"]
这将告知 setuptools 在何处查找包。它不会更改项目的名称或包的导入名称。如果已有 [tool.setuptools.packages.find] 表,请直接编辑该表,而不是添加第二个表。TOML 文件中同一表定义不能重复。
要将发现范围限制在一个包及其子包内,请添加与完整点分包名匹配的 include 模式:
[tool.setuptools.packages.find]
where = ["src"]
include = ["my_package*"]
将 my_package 替换为实际导入的包名。* 允许该模式匹配诸如 my_package.tools 的子包;模式会与完整的包名进行匹配。您还可以排除选定的包,例如 exclude = ["my_package.tests*"]。Setuptools 在其包发现指南中记录了这些包含和排除模式以及 where。
选择发现机制如何处理命名空间包
默认情况下,setuptools 的 pyproject.toml 发现在扫描时会包含隐式命名空间包:即使目录中不包含 __init__.py,也可以将其视作包。如果您的包特意使用了 PEP 420 命名空间包,请保留此默认设置。如果每个包都应该有一个 __init__.py,您可以关闭命名空间扫描:
[tool.setuptools.packages.find]
where = ["src"]
namespaces = false
使用此设置后,没有 __init__.py 的目录将不会被发现为包。因此,构建好的分发包中缺少某个包,可能是由于搜索位置、include 或 exclude 模式或命名空间设置引起的。打包指南讨论了此行为,并展示了如何将发现范围限制在选定的命名空间包中。Python 打包用户指南:打包命名空间包
了解何时自动发现即已足够
对于简单的 src/my_package 项目,您可能根本不需要发现表。当未指定 packages 和 py-modules 时,Setuptools 能够识别常见的布局。当您需要缩小包的选择范围、处理不太常规的目录树或使源目录明确无歧义时,请添加显式配置。除非您打算在包目录树发生变化时持续维护包列表,否则避免单独硬编码包列表;显式列表很容易遗漏新添加的子包。
src 布局还意味着从存储库根目录运行 Python 不会自动将该包加入导入路径。这是符合预期的:setuptools 文档指出,要以这种方式从源码签出中使用该包,需要进行可编辑安装(editable install)。发现配置控制的是哪些内容会被包含在分发包中;它不能替代将项目安装到用于开发的 Python 环境中。Setuptools:包发现和命名空间包
参考来源
使用 pyproject.toml 文件配置 setuptools — setuptools
包发现和命名空间包 — setuptools
打包命名空间包 — Python Packaging Authority