You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

咨询:无src结构下将setup.py置于包根目录构建Python包的方法

关于setuptools包结构与构建方案的疑问

我正在学习setuptools,现有一个Python包结构如下:

package1
     ├──setup.py
     ├── __init__.py
     ├── module1.py
     └── submodule1
         └── __init__.py

我希望将setup.py放在package1目录(即GitHub仓库根目录)内,构建分发版时将package1的文件打包为名为package1的包,同时排除setup.py文件。目前我使用的是带src的结构:

production
  ├──setup.py
  └──src
      └──package1
         ├── __init__.py
         ├── module1.py
         └── submodule1
             └── __init__.py

这样设置是为了让克隆仓库的用户可直接执行python -m build进行构建,请问该方案是否可行?有无其他实现方式?


方案可行性分析

你采用的带src的结构完全可行,而且这是Python打包社区推荐的最佳实践之一。这种结构的优势很明确:

  • 彻底避免本地开发时的包导入混淆(不会出现直接导入当前目录下的package1而非已安装版本的问题)
  • 克隆仓库的用户确实可以直接在根目录执行python -m build,build工具能自动识别src目录下的包并正确打包,且setup.py不会被包含到最终的分发包里,完全符合你的需求。

其他实现方式

如果不想用src结构,也有两种常用方案:

1. 直接在根目录放置setup.py,通过配置排除setup.py

保持你最初的目录结构(setup.py和package1同属根目录),然后通过以下两种方式排除setup.py:

  • 在setup.py中配置:
    调用setup()时,通过参数控制排除文件,示例:
    from setuptools import setup, find_packages
    
    setup(
        name="package1",
        packages=find_packages(),
        exclude_package_data={"": ["setup.py"]}
    )
    
  • 使用MANIFEST.in文件:
    在根目录创建MANIFEST.in,写入:
    exclude setup.py
    
    这个文件会告诉setuptools构建分发版时排除指定文件。
    不过这种方式有个潜在问题:本地开发时,如果你在根目录运行脚本,可能会直接导入当前目录的package1,而非已安装的版本,容易引发调试混乱。

2. 使用pyproject.toml替代setup.py(现代打包方式)

现在Python打包更推荐使用pyproject.toml来声明构建依赖和配置,配合setup.cfg或者直接在pyproject.toml里写包配置,不管是src结构还是非src结构都适用。
比如src结构下的pyproject.toml示例:

[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "package1"
version = "0.1.0"
packages = ["package1"]
package-dir = {"": "src"}

这种方式更简洁,也能自动排除根目录的配置文件,用户同样可以直接执行python -m build构建。

内容的提问来源于stack exchange,提问作者grexor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 13:30:17