Monorepo中如何让pyinvoke在子目录加载上级+当前目录的任务?
在Monorepo中实现多层级pyinvoke任务的跨目录访问
核心思路
在子目录的tasks/__init__.py中,通过动态导入上级目录的任务集合,并将其作为独立命名空间添加到当前任务集合中,同时确保Python能正确找到上级的tasks模块。
具体实现步骤
1. 确保顶级任务集合配置正确
repo_top/tasks/__init__.py中需正确创建任务集合并导入子模块:
from invoke import Collection from . import install # 初始化顶级任务集合 ns = Collection() # 添加install模块的任务到顶级集合 ns.add_collection(install)
2. 修改子目录的任务集合配置
编辑repo_top/apps/tasks/__init__.py,添加路径处理和顶级任务导入逻辑:
import sys from pathlib import Path from invoke import Collection from . import lambdas # 自动定位repo_top目录(向上查找包含tasks目录的父级) def find_root_tasks_dir(current_dir): while current_dir != current_dir.parent: tasks_dir = current_dir / "tasks" if tasks_dir.exists() and (tasks_dir / "__init__.py").exists(): return current_dir current_dir = current_dir.parent return None # 获取当前文件所在目录的父级(apps目录) current_apps_dir = Path(__file__).parent.parent.resolve() repo_top = find_root_tasks_dir(current_apps_dir) if repo_top: # 将repo_top加入Python路径,确保能导入顶级tasks模块 sys.path.insert(0, str(repo_top)) # 导入顶级任务集合 from tasks import ns as top_tasks_ns # 将顶级任务作为命名空间"top"添加到当前集合 # 也可以自定义命名,比如"root"或"global" current_ns = Collection() current_ns.add_collection(lambdas) current_ns.add_collection(top_tasks_ns, name="top") else: # 找不到顶级tasks时,仅加载当前目录任务 current_ns = Collection(lambdas) # 导出当前任务集合 ns = current_ns
3. 验证效果
进入repo_top/apps目录,执行invoke --list,会看到如下输出:
Available tasks: lambdas.python-build-lambda # 子目录自身的任务 top.install.bootstrap-devx # 顶级目录的任务(带命名空间前缀)
注意事项
- 命名空间隔离:使用命名空间(如
top)可以避免不同层级任务名冲突,建议保留该设置。如果不需要前缀,直接合并集合(current_ns.add_collection(top_tasks_ns)),但需确保任务名唯一。 - 路径可靠性:使用
Path和绝对路径处理,避免相对路径在不同运行目录下的问题。 - 扩展性:如果有更多层级的子目录,可复用
find_root_tasks_dir函数,自动向上查找顶级任务集合,无需硬编码路径。
内容的提问来源于stack exchange,提问作者Robert J Berger
相关产品推荐
相关产品推荐

