复杂Src布局下Python包构建:导入配置与VS Code自动补全问题
拆分Python项目为独立子包并支持顶层安装与VS Code自动补全
需求
- 将工具拆分至独立仓库/包,支持单独使用
- 通过顶层
setup.py安装任意子工具包集合 - 实现指定导入方式(子包缺失时无需支持)
- 解决VS Code中
cool_code及其子包的自动补全问题
项目目录结构
│ └──── cool_code ├── setup.py ├── src | ├── __init__.py │ └── cool_top_level_stuff.py ── pkgA │ ├── other_coding_language_folders... | └── python | ├──setup.py | ├──data | ├──docs | ├──examples | ├──test | └──src | ├── __init__.py | └── funkA.py ── pkgB │ ├── other_coding_language_folders... | └── python | ├──setup.py | ├──data | ├──docs | ├──examples | ├──test | └──src | ├── __init__.py | └── funkB.py ──pkgC │ ├── other_coding_language_folders... | └── python | ├──setup.py | ├──data | ├──docs | ├──examplesa | ├──test | └──src | ├── __init__.py | └── funkC.py └──sub_category ├── pkgD │ ├── other_coding_language_folders... | └── python | ├──setup.py | ├──data | ├──docs | ├──examples | ├──test | └──src | ├── __init__.py | └── funkD.py └── pkgE ├── other_coding_language_folders... └── python ├──setup.py ├──data ├──docs ├──examples ├──test └──src ├── __init__.py └── funkE.py
期望导入方式
import cool_code import cool_code.pkg_A from cool_code.pkg_B.funkB import funkB import cool_code.sub_category.pkg_D as pkg_D
当前setup.py配置
from setuptools import setup, find_packages, extension,find_namespace_packages if __name__ == '__main__': setup( name='cool_code', version='1.2.3', package_dir={ # 'cool_code':'src', 'cool_code.pkg_A': 'pkg_A/python/src/', 'cool_code.pkg_B': 'pkg_B/python/src/', 'cool_code.pkg_C': 'pkg_C/python/src/', 'cool_code.sub_category.pkg_D': 'sub_category/pkg_D/python/src/', 'cool_code.sub_category.pkg_E': 'sub_category/pkg_E/python/src/', }, packages=[ # 'cool_code' 'cool_code.pkg_A', 'cool_code.pkg_B', 'cool_code.pkg_C', 'cool_code.sub_category.pkg_D', 'cool_code.sub_category.pkg_E', ], # py_modules=[ # 'cool_code.pkg_A', # 'cool_code.pkg_B', # 'cool_code.pkg_C', # 'cool_code.sub_category.pkg_D', # 'cool_code.sub_category.pkg_E', # ], # scripts = [], )
遇到的问题
- 多次修改
setup.py仍无法实现正确导入 - 不确定是否需要
py_modules字段 - 曾实现部分导入,但VS Code中
cool_code及其子包无自动补全,推测是Python命名空间反向传播导致,VS Code仅识别显式文件模块
解决方案
1. 调整显式命名空间结构
为让VS Code识别命名空间层级,在顶层src/cool_code下创建对应子目录与空__init__.py:
cool_code/src/cool_code/ ├── __init__.py # 已存在 ├── cool_top_level_stuff.py ├── pkg_A/ │ └── __init__.py ├── pkg_B/ │ └── __init__.py ├── pkg_C/ │ └── __init__.py └── sub_category/ ├── __init__.py ├── pkg_D/ │ └── __init__.py └── pkg_E/ └── __init__.py
这些空文件用于告知VS Code语言服务识别命名空间结构,配合setuptools命名空间包机制。
2. 修改顶层setup.py配置
使用find_namespace_packages并正确映射包路径:
from setuptools import setup, find_namespace_packages if __name__ == '__main__': setup( name='cool_code', version='1.2.3', package_dir={ 'cool_code': 'src/cool_code', 'cool_code.pkg_A': 'pkgA/python/src', 'cool_code.pkg_B': 'pkgB/python/src', 'cool_code.pkg_C': 'pkgC/python/src', 'cool_code.sub_category.pkg_D': 'sub_category/pkgD/python/src', 'cool_code.sub_category.pkg_E': 'sub_category/pkgE/python/src', }, packages=find_namespace_packages(include=[ 'cool_code', 'cool_code.pkg_A', 'cool_code.pkg_B', 'cool_code.pkg_C', 'cool_code.sub_category.*' ]), # 无需py_modules,packages机制已覆盖需求 )
find_namespace_packages自动识别命名空间包,include参数指定要包含的子包范围package_dir映射完整命名空间路径到对应源码目录- 顶层
cool_code指向src/cool_code,确保import cool_code正常导入
3. 子包独立安装配置
以pkgA/python/setup.py为例,配置为命名空间包的一部分:
from setuptools import setup, find_namespace_packages setup( name='cool_code.pkg_A', version='1.0.0', package_dir={'cool_code.pkg_A': 'src'}, packages=find_namespace_packages(include=['cool_code.pkg_A']), )
单独安装子包时,会自动注册到cool_code命名空间下。
4. 修复VS Code自动补全
在项目根目录创建.vscode/settings.json,添加源码路径到分析路径:
{ "python.analysis.extraPaths": [ "${workspaceFolder}/src", "${workspaceFolder}/pkgA/python/src", "${workspaceFolder}/pkgB/python/src", "${workspaceFolder}/pkgC/python/src", "${workspaceFolder}/sub_category/pkgD/python/src", "${workspaceFolder}/sub_category/pkgE/python/src" ] }
同时确保VS Code已选择项目对应的Python解释器。
验证步骤
- 开发模式安装顶层包:
pip install -e . - 测试导入代码是否正常运行
- 检查VS Code自动补全是否生效
内容的提问来源于stack exchange,提问作者Gibson Strickland
相关产品推荐
相关产品推荐

