Setuptools package discovery配置:仅安装base与mypkg1排除mypkg2
问题描述
项目目录结构
项目根目录 ├── src │ ├── mypkg1 │ │ ├── module1.py │ │ ├── module2.py │ │ └── __init__.py │ ├── mypkg2 │ │ ├── module1.py │ │ └── __init__.p │ ├── setup.py │ └── requirements.py └── base ├── init.py └── module1.py
补充说明:
src目录与base目录处于同一层级,均位于项目根目录下。
需求为正确配置setup.py,实现仅安装base和mypkg1包、排除mypkg2包的效果。
此前尝试的两种方案均失效:
- 直接在
packages参数中指定['base','mypkg1']未生效 - 直接调用
find_packages()仅能识别到src下的mypkg1和mypkg2,无法识别同级的base包
解决方案
前置修正
首先需要修正两个包结构的笔误,否则Python无法将对应目录识别为合法包:
base目录下的初始化文件必须命名为__init__.py,当前命名为init.py不符合规范mypkg2下的初始化文件后缀缺失,应补全为__init__.py(如果刻意不想让mypkg2被识别也可以保留该命名,更规范的做法是通过配置显式排除)
核心配置逻辑
配置失效的核心原因是setup.py存放在src目录下,默认情况下setuptools只会搜索setup.py所在目录下的包,自然无法定位到上层目录的base包,直接写包名也因为缺少路径映射找不到对应位置。
将以下内容写入src/setup.py即可实现需求:
from setuptools import setup import os # 获取项目根目录的绝对路径(setup.py在src下,根目录是src的上一级) PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) setup( name="your-package-name", version="0.0.1", # 显式声明需要安装的包 packages=["mypkg1", "base"], # 配置包名和实际目录的映射关系 package_dir={ "mypkg1": os.path.join("src", "mypkg1"), "base": os.path.join(PROJECT_ROOT, "base") }, # 依赖项可自行从requirements.py或requirements.txt读取 install_requires=[] )
如果希望用find_packages()自动扫描,可以替换为以下配置:
from setuptools import setup, find_packages import os PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) setup( name="your-package-name", version="0.0.1", # 分别扫描src和根目录,只包含需要的包,排除mypkg2 packages=find_packages( where=[PROJECT_ROOT, os.path.join(PROJECT_ROOT, "src")], include=["mypkg1", "base"], exclude=["mypkg2"] ), package_dir={ "": [PROJECT_ROOT, os.path.join(PROJECT_ROOT, "src")] }, install_requires=[] )
验证方式
配置完成后在src目录下执行pip install -e .进行可编辑安装,安装完成后进入Python交互环境:
- 执行
import mypkg1、import base无报错,说明两个包安装成功 - 执行
import mypkg2报ModuleNotFoundError,说明排除规则生效
内容的提问来源于stack exchange,提问作者Piyush S. Wanare
相关产品推荐
相关产品推荐

