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

单仓库拆分多Python包后setup.py位置不当致安装失败的解决方案

问题描述

我是开源程序GridCal的开发者,该程序包含基于Qt的GUI和计算引擎。最初因实用考量将GUI与引擎置于同一包下,如下结构可正常生成并上传PyPI包,原因是setup.py与GridCal包同级:

repository_folder
|
|_ src
    |_ GridCal
    |     |_ GUI
    |     |_ Core
    |     |_ IO
    |     |_ Simulations
    |     |_ __init__.py
    |     
    |_ setup.py 
    |_ upload_to_pypi.py

近期我将代码拆分为GridCal和GridCalEngine两个包,新结构如下:

repository_folder
|
|_ src
    |_ GridCal
    |     |_ GUI
    |     |_ __init__.py
    |     |_ setup.py 
    |
    |_ GridCalEngine
    |     |_ Core
    |     |_ IO
    |     |_ Simulations
    |     |_ __init__.py
    |     |_ setup.py 
    |
    |_ upload_to_pypi.py

该拆分结构便于开发,GUI可正常引用引擎,也能生成并上传PyPI包,但安装时失败,原因是setup.py未像之前那样置于包外。已参考相关资源但未找到可安装包的解决方案,请问如何解决setup.py的位置问题?

解决方案

方案1:调整目录结构,将setup.py移至包外(推荐)

这是最贴合Python包规范的做法,把每个包的setup.py放到对应包的同级目录,而非包内部。调整后的结构可参考两种方式:

方式A:同一src目录下区分不同包的构建文件

repository_folder
|
|_ src
    |_ GridCal
    |     |_ GUI
    |     |_ __init__.py
    |
    |_ GridCalEngine
    |     |_ Core
    |     |_ IO
    |     |_ Simulations
    |     |_ __init__.py
    |
    |_ setup_gridcal.py  # 原GridCal内的setup.py迁移至此,可改名区分两个包的构建文件
    |_ setup_engine.py   # 原GridCalEngine内的setup.py迁移至此
    |_ upload_to_pypi.py

方式B:给每个包单独创建独立目录

repository_folder
|
|_ packages
    |_ GridCal
    |     |_ src
    |     |    |_ GridCal
    |     |         |_ GUI
    |     |         |_ __init__.py
    |     |_ setup.py
    |
    |_ GridCalEngine
    |     |_ src
    |     |    |_ GridCalEngine
    |     |         |_ Core
    |     |         |_ IO
    |     |         |_ Simulations
    |     |         |_ __init__.py
    |     |_ setup.py
|
|_ upload_to_pypi.py

两种结构都让setup.py位于包的根目录(与该包的源代码文件夹同级),符合PyPA的包结构规范,安装时能正确识别包的根路径。

方案2:修改setup.py的package_dir参数(无需调整目录)

如果不想改动现有目录结构,可在包内的setup.py中通过package_dir参数,明确告诉setuptools包的源代码位置。

以GridCalEngine内的setup.py为例,修改核心配置:

from setuptools import setup, find_packages

setup(
    name="GridCalEngine",
    # 其他元数据配置...
    package_dir={"": "."},  # 指定包的根目录为当前setup.py所在的目录
    packages=find_packages(where="."),  # 在当前目录下查找包模块
    # 其他依赖、脚本等配置...
)

GridCal内的setup.py做同样修改即可。这种方式能临时解决安装问题,但长期维护建议遵循标准结构,避免后续出现路径相关的隐藏问题。

方案3:改用pyproject.toml+setup.cfg(现代包规范)

现在Python官方推荐使用pyproject.toml声明构建依赖,配合setup.cfg管理包的元数据,可完全替代传统的setup.py(或仅保留极简的空setup.py兼容旧工具)。

以GridCalEngine为例,调整后的结构:

repository_folder
|
|_ src
    |_ GridCalEngine
    |     |_ Core
    |     |_ IO
    |     |_ Simulations
    |     |_ __init__.py
    |
    |_ pyproject.toml
    |_ setup.cfg
    |_ upload_to_pypi.py

pyproject.toml示例:

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

setup.cfg示例:

[metadata]
name = GridCalEngine
version = 0.1.0
author = Santi Peñate-Vera
description = GridCal's core calculation engine

[options]
packages = find:
package_dir =
    = src
python_requires = >=3.8

这种方式无需纠结setup.py的位置,更符合现代Python包的构建规范,同时能简化发布和维护流程。

内容的提问来源于stack exchange,提问作者Santi Peñate-Vera

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 08:05:55