本文详解如何通过 pip install -e . 正确安装采用“ad-hoc 布局”的本地 python 项目,解决 find_packages(where='mypkg') 报错及子包无法导入的问题,并说明 package_dir 的关键作用。
在开发多层嵌套的本地 Python 项目时,常见的目录结构是将实际包代码置于子目录(如 mypkg/)下,而非直接放在项目根目录——这种布局被称为 ad-hoc layout(非标准布局)。此时若仅依赖 find_packages() 而不显式声明源码映射关系,pip install -e . 很可能失败或导致包内容为空。
你遇到的错误:
error: package directory 'subpkg1' does not exist
根本原因在于:find_packages(where='mypkg') 告诉 setuptools 去 mypkg/ 目录里找包,但 setuptools 仍默认从当前目录(即 project_root_directory)解析包路径。当它尝试验证 subpkg1 是否为合法包时,会按相对路径 subpkg1/ 查找(即根目录下的 subpkg1/),而非 mypkg/subpkg1/,因此报错——尽管该子包真实存在于 mypkg/ 内。
✅ 正确解法是同时指定两件事:
因此,你的 setup.py 应修正为:
from setuptools import setup, find_packages
setup(
name="Code",
author="Me",
author_email="Me",
description="Code",
packages=find_packages(where="mypkg"), # ✅ 扫描 mypkg/ 下的所有包
package_dir={"": "mypkg"}, # ✅ 关键!将 "" → "mypkg" 映射
python_requires=">=3.6",
)? 补充说明:package_dir={"": "mypkg"} 表示“所有未显式声明前缀的包(即顶层包 mypkg)均来自 mypkg/ 目录”。这使 find_packages(where="mypkg") 扫描到的 subpkg1、subpkg2 等能被正确定位为 mypkg.subpkg1、mypkg.subpkg2。
完成修改后,执行:
pip install -e .
即可成功以可编辑模式安装整个包结构。之后可在 Python 中正常导入:
from mypkg.subpkg1 import module1 from mypkg.subpkg2.module2 import some_function import mypkg
⚠️ 注意事项:
总结:find_packages(where=...) 只负责“发现”,而 package_dir 才真正决定“如何解析路径”。二者必须协同配置,才能让 ad-hoc 布局的本地项目被 pip 正确识别、安装与导入。