首页
/ Kedro 项目配置中枢深度解析:kedro.framework.project 模块的 settings、日志与管道自动发现机制

Kedro 项目配置中枢深度解析:kedro.framework.project 模块的 settings、日志与管道自动发现机制

2026-09-14 23:53:29作者:傅爽业Veleda

导读

本文聚焦 Kedro 框架中的 kedro.framework.project 模块——它是连接"Kedro 项目"与"Kedro 框架内核"的配置中枢。无论你是想通过 settings.py 定制配置加载器、数据目录、会话与上下文类,还是想理解 kedro run 时管道(pipeline)是如何被自动发现和注册的,本模块都是绕不开的核心。读完本文,你将掌握该模块公开的四个核心函数(configure_loggingconfigure_projectfind_pipelinesvalidate_settings)、全部可配置项及其默认值、底层 Dynaconf 校验机制,以及日志配置的安全校验规则,并能够据此独立定制自己的 Kedro 项目。


模块定位:项目与框架之间的"配置适配层"

官方 API 文档 kedro.framework.project.md 对该模块的定义是:

"kedro.framework.project module provides utility to configure a Kedro project and access its settings."

即:该模块负责用用户项目中的配置(settings.pypipeline_registry.py)去填充框架的运行参数,并提供统一的项目级访问入口。其完整实现位于 kedro/framework/project/init.py

模块公开了四个顶层函数:

函数 说明
configure_logging(logging_config) 根据 logging_config 字典配置项目日志
configure_project(package_name, preserve_logging=False) settings.pypipeline_registry.py 中的值填充项目设置,完成项目配置
find_pipelines(raise_errors=False, pipelines_to_find=None) 自动发现所有暴露 create_pipeline 函数的模块化管道
validate_settings() 提前(eagerly)校验 settings 模块可被正常导入

此外,模块还导出了四个进程级全局单例对象settingspipelinesLOGGINGPACKAGE_NAME,它们是整个 Kedro 框架(会话、上下文、CLI)读取项目信息的公共入口。


全局单例对象:框架访问项目的四个入口

kedro/framework/project/init.py 中定义了四个模块级对象:

PACKAGE_NAME = None
LOGGING = _ProjectLogging()
settings = _ProjectSettings()
pipelines = _ProjectPipelines()

它们各自的角色如下:

  • PACKAGE_NAME:全局记录当前已配置的项目包名,供 validate_settings() 以及 Windows 上 ParallelRunner 派生子进程时使用(源码注释对此有明确说明)。
  • settings:基于 Dynaconf LazySettings 实现的 _ProjectSettings 实例,承载所有可配置项与默认值,并挂载了类型/继承关系校验器。
  • pipelines_ProjectPipelines 实例,一个只读、懒加载的字典式对象,首次访问时才真正导入并执行 register_pipelines()
  • LOGGING_ProjectLogging 实例,一个 UserDict,负责定位、校验并应用日志配置。

_ProjectSettings:带校验规则与默认值的配置表

_ProjectSettings 继承了 dynaconf.LazySettings,其构造器把 12 个 Validator 注册进 Dynaconf(见 kedro/framework/project/init.py)。完整配置项、默认值与校验方式如下表:

配置项 默认值 校验方式 用途
CONF_SOURCE "conf" 普通 Validator 配置目录名
HOOKS () 普通 Validator 项目钩子实例元组
CONTEXT_CLASS kedro.framework.context.KedroContext _IsSubclassValidator 上下文类,必须是指定类的子类
SESSION_CLASS kedro.framework.session.KedroSession _HasSharedParentClassValidator 会话类,必须共享指定类的直接父类
SESSION_STORE_CLASS kedro.framework.session.store.BaseSessionStore _IsSubclassValidator 会话存储类
SESSION_STORE_ARGS {} 普通 Validator 传给会话存储构造器的关键字参数
DISABLE_HOOKS_FOR_PLUGINS () 普通 Validator 禁用钩子自动注册的插件名
RUNNER_MODULE_ALLOWLIST () 普通 Validator 允许作为 runner 的模块白名单
CONFIG_LOADER_CLASS kedro.config.OmegaConfigLoader _HasSharedParentClassValidator 配置加载器类
CONFIG_LOADER_ARGS {"base_env": "base", "default_run_env": "local"} 普通 Validator 配置加载器构造参数
DATA_CATALOG_CLASS kedro.io.DataCatalog _ImplementsCatalogProtocolValidator 数据目录类,须实现 CatalogProtocol
DATASET_VALIDATION True 普通 Validator(布尔值) 是否启用数据集校验

这些默认值在测试 tests/framework/project/test_settings.py 中被逐一断言,例如:

def test_settings_without_configure_project_shows_default_values():
    assert len(settings.HOOKS) == 0
    assert settings.SESSION_STORE_CLASS is BaseSessionStore
    assert settings.CONTEXT_CLASS is KedroContext
    assert settings.CONF_SOURCE == "conf"
    assert settings.CONFIG_LOADER_CLASS == OmegaConfigLoader
    assert settings.CONFIG_LOADER_ARGS == {
        "base_env": "base",
        "default_run_env": "local",
    }
    assert settings.DATA_CATALOG_CLASS == DataCatalog

三类自定义校验器:配置错误的"提前哨兵"

为保证用户在 settings.py 中填入的值符合框架预期,模块实现了三个 Dynaconf Validator:

  • _IsSubclassValidator:要求配置值是指定默认类的子类,否则抛出 ValidationError,错误信息形如 Invalid value 'xxx' received for setting 'CONTEXT_CLASS'. It must be a subclass of '...KedroContext'.源码位置)。
  • _ImplementsCatalogProtocolValidator:实例化配置值并检查其是否为 CatalogProtocol 的实例,用于 DATA_CATALOG_CLASS源码位置)。
  • _HasSharedParentClassValidator:取默认类 MRO 中的直接父类(即抽象基类),检查其是否出现在配置值类的 MRO 中,用于 SESSION_CLASSCONFIG_LOADER_CLASS。以 ConfigLoader 为例,其 MRO 为 <a href="https://link.gitcode.com/i/4fef77e04eaeea8b06fb720b2fea467e" target="_blank">ConfigLoader, AbstractConfigLoader, abc.ABC, object],校验逻辑正是取 AbstractConfigLoader 这个直接父类来判断继承关系([源码位置)。

这意味着:settings.py 中把 CONTEXT_CLASS 配成一个与 KedroContext 无关的类、或把 DATA_CATALOG_CLASS 配成未实现 CatalogProtocol 的类,都会在配置阶段立即收到明确报错,而不是在运行期遇到难以排查的诡异崩溃。


configure_project:项目配置的总入口

configure_project(package_name, preserve_logging=False) 是模块最核心的函数(源码位置),它按顺序完成四件事:

def configure_project(package_name: str, preserve_logging: bool = False) -> None:
    settings_module = f"{package_name}.settings"
    settings.configure(settings_module)

    pipelines_module = f"{package_name}.pipeline_registry"
    pipelines.configure(pipelines_module)

    global PACKAGE_NAME
    PACKAGE_NAME = package_name

    if PACKAGE_NAME:
        LOGGING.set_project_logging(PACKAGE_NAME, preserve_logging=preserve_logging)
  1. 配置 settings:让 Dynaconf 加载 <package_name>.settings 模块中的值并覆盖默认值;
  2. 配置 pipelines:记录 <package_name>.pipeline_registry 模块路径,但此时并不导入执行,真正的懒加载发生在首次访问 pipelines 字典时;
  3. 记录 PACKAGE_NAME:供 validate_settings() 与并行运行时的子进程使用;
  4. 为项目包注册 INFO 级别日志:若 preserve_logging=True,则跳过重新执行 dictConfig,避免覆盖运行时动态添加的 handler(例如 FastAPI 等长驻进程中自定义的日志处理器),见 set_project_logging 的实现。

谁在调用 configure_project

最常见调用者是 bootstrap_project,它读取项目根目录 pyproject.toml[tool.kedro] 段得到 package_name 后:

def bootstrap_project(project_path: str | Path) -> ProjectMetadata:
    project_path = Path(project_path).expanduser().resolve()
    metadata = _get_project_metadata(project_path)
    _add_src_to_path(metadata.source_dir, project_path)
    configure_project(metadata.package_name)
    return metadata

即"解析 pyproject.toml → 把 src/ 加入 sys.path → 调用 configure_project"。因此,凡是经过 kedro CLI、KedroSession 或 IPython 扩展启动的项目,都会自动完成配置,开发者通常无需手动调用。

模板中的 settings.py:所有可配置项的官方注释范本

Kedro 项目模板生成的 settings.py 用注释完整罗列了全部可配置项,其中唯一默认启用的是:

CONFIG_LOADER_ARGS = {
    "base_env": "base",
    "default_run_env": "local",
    # "config_patterns": {
    #     "spark" : ["spark*/"],
    #     "parameters": ["parameters*", "parameters*/**", "**/parameters*"],
    # }
}

其余如 HOOKSDISABLE_HOOKS_FOR_PLUGINSSESSION_CLASSSESSION_STORE_CLASSSESSION_STORE_ARGSCONF_SOURCECONFIG_LOADER_CLASSCONTEXT_CLASSDATA_CATALOG_CLASS 均以注释形式给出用法示例,用户按需取消注释并填入自己的类/值即可。


configure_logging 与日志配置的安全校验

configure_logging(logging_config) 是对 LOGGING.configure() 的一行转发(源码位置),其本质是执行 logging.config.dictConfig。但在应用之前,_ProjectLogging 会做两层安全处理:

  1. 拒绝 () 工厂键_validate_logging_config 递归扫描配置字典,一旦发现 "()" 键立即抛出 ValueError,因为 dictConfig 会将其当作可调用工厂执行,存在任意代码执行风险(源码位置)。
  2. 校验 class 值必须是合法的日志类_resolve_logging_class 要求配置中引用的类必须是 logging.Handlerlogging.Formatterlogging.Filter 的子类,否则抛错;对通过校验的 Filter 子类,_prepare_logging_config 会把 class 转换为内部的 () 调用入口,从而在不开后门的前提下支持自定义过滤器(源码位置)。

日志配置文件的三级定位

_ProjectLogging.__init__源码位置)按以下优先级定位日志配置:

  1. 环境变量 KEDRO_LOGGING_CONFIG 指定的路径(最高优先级);
  2. 项目内的 conf/logging 配置文件(通过 find_config_file("conf/logging") 查找);
  3. 框架自带默认配置:若环境中安装了 rich,则使用 rich_logging.yml(基于 kedro.logging.RichHandler 的富文本日志);否则退化为 default_logging.ymlStreamHandler + 10MB 轮转文件 info.log、20 个备份)。

validate_settings:把导入错误提前暴露

validate_settings() 的设计动机非常实际:Dynaconf 会静默吞掉 settings 模块的导入错误,导致用户最终只看到一句晦涩的 Expected an instance of ConfigLoader, got NoneType instead。为此,该函数在 PACKAGE_NAME 已配置的前提下主动执行 importlib.import_module(f"{PACKAGE_NAME}.settings"),把语法错误、缺失依赖等问题提前暴露出来(源码位置)。

其边界行为:

  • PACKAGE_NAMENone(项目尚未配置),抛出 ValueError,提示应先通过 bootstrap_project 配置项目;
  • 若项目根本没有 settings.py,则打印警告 No 'settings.py' found, defaults will be used. 并继续使用默认值(对应测试 test_validate_settings_without_settings_file)。

find_pipelines:管道自动发现机制

Kedro 0.18.3 及之后创建的项目默认在 pipeline_registry.py 中调用 find_pipelines() 实现管道自动注册(模板 pipeline_registry.py):

def register_pipelines() -> dict[str, Pipeline]:
    pipelines = find_pipelines(raise_errors=True)
    pipelines["__default__"] = sum(pipelines.values())
    return pipelines

发现规则

find_pipelines(raise_errors=False, pipelines_to_find=None) 的完整逻辑位于 kedro/framework/project/init.py#L591-L731,核心规则如下:

  • 前置条件PACKAGE_NAME 必须已配置,否则抛出 RuntimeError(提示先调用 configure_project)。
  • __default__ 管道:优先尝试导入 <package_name>.pipeline 模块(对应若干 starter 使用的简化项目结构),通过 _create_pipeline 校验后作为 __default__;若不存在该模块则用空管道 pipeline([]) 兜底。
  • 遍历 pipelines:通过 importlib.resources.files(f"{PACKAGE_NAME}.pipelines") 遍历包内子目录,跳过 __pycache__、隐藏目录(以 . 开头)以及不在 pipelines_to_find 白名单中的目录
  • 模块要求:每个管道模块必须暴露 create_pipeline() 函数,且其返回值必须是 Pipeline 实例。不满足时:
    • raise_errors=False(默认):发出 UserWarning 并跳过该管道;
    • raise_errors=True:抛出 ImportError / KeyError,例如 Pipeline 'xxx' not found
  • 选择性加载pipelines_to_find 参数或 CLI 设置的过滤器 pipelines._requested_pipelines 可以只加载指定管道;若为 None 或包含 "__default__",则加载全部。

_create_pipeline 的校验(源码位置)会给出两种清晰的警告:模块没有 create_pipeline 函数、或该函数返回的不是 Pipeline 对象。

懒加载字典 _ProjectPipelines

pipelines 对象是一个 MutableMapping 风格的只读懒加载字典,其设计目标在源码 docstring 中写得很清楚(源码位置):

  1. 统一导入方式:框架在 bootstrap_project 之前并不知道项目存在,因此对象必须懒初始化,保证任何时刻 from kedro.framework.project import pipelines 都可用;
  2. 加速 CLI:加载管道需要导入大量相关模块,懒加载避免每次执行 kedro -h 等命令都付出此开销;
  3. 容错:开发期管道损坏很常见,但不应影响 CLI 其余功能正常使用。

每次 configure()set_requested() 调用都会使数据失效,从而在下次字典访问时重新执行 register_pipelines()__iter__keys()values() 等方法均返回快照而非实时视图,避免并发修改导致的问题。

注意:源码 docstring 特别警告——在模块导入期(import time)访问 pipelines 不受支持且可能死锁。因为 _load_data() 在持有实例锁的情况下执行 importlib.import_module 与用户 register_pipelines(),若另一个线程正在导入同一模块并等待实例锁,而本线程又等待 Python 的模块导入锁,就会互相等待形成死锁。因此不要在 pipeline_registry.py 导入的辅助模块的模块级代码里读取 pipelines[...]


与运行时的联动:session 如何消费这些配置

配置完成的 settingspipelines 会被 KedroSession 消费:会话模块顶部通过 from kedro.framework.project import pipelines, settings, validate_settings 导入这些全局对象,在创建上下文时按 settings.CONFIG_LOADER_CLASSsettings.CONFIG_LOADER_ARGS 实例化配置加载器,按 settings.DATA_CATALOG_CLASS 实例化数据目录,并通过 pipelines<a href="https://link.gitcode.com/i/b3417025c5030a07f4b7b1737f2e71ab" target="_blank">...] 取得注册的管道字典。测试 [tests/framework/project/test_settings.py 中 MyContextMyDataCatalogMyKedroSessionProjectHooks 四个自定义类同时被配置并被断言生效,正是对这一联动链路的端到端验证。

管道发现与注册行为的专项测试分别位于 tests/framework/project/test_pipeline_discovery.pytests/framework/project/test_pipeline_registry.py;日志配置(含 KEDRO_LOGGING_CONFIG、非法 () 键、非法日志类等场景)的测试位于 tests/framework/project/test_logging.py


实战小结:定制一个 Kedro 项目的标准姿势

综合以上机制,自定义项目配置的标准流程可归纳为:

  1. <package_name>/settings.py 中覆盖配置项(参考项目模板生成的 settings.py 注释,替换 CONTEXT_CLASSCONFIG_LOADER_CLASSDATA_CATALOG_CLASSSESSION_STORE_ARGS 等);
  2. 若需手工注册管道而非自动发现,直接在 <package_name>/pipeline_registry.py 中编写自己的 register_pipelines() 返回管道字典;否则保持模板中 find_pipelines(raise_errors=True) 的写法;
  3. 通过 bootstrap_project 或 Kedro CLI 启动项目,configure_project 会自动执行,validate_settings 会在启动早期暴露任何 settings 导入问题;
  4. 如需覆盖日志配置,设置环境变量 KEDRO_LOGGING_CONFIG 指向自定义 yml,或编辑 conf/logging.yml——注意不要使用 () 工厂键,且引用的自定义类必须是 logging.Handler/Formatter/Filter 的子类。

kedro.framework.project 正是以这种"默认值 + 强校验 + 懒加载 + 安全过滤"的组合拳,保证了 Kedro 项目配置的健壮性、可扩展性与启动性能三者之间的平衡。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
34
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.21 K
2.81 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
945
1.86 K
docsdocs
暂无描述
Markdown
906
5.84 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
537
607
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
864
1.36 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
4.28 K
1.03 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.39 K
1.48 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
550
401
flutter_flutterflutter_flutter
本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本,由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用,3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。
Dart
1.19 K
347