2. 扩展生命周期管理

任务说明

本案例要求实现一个Omniverse Kit扩展,在扩展生命周期回调on_startup和on_shutdown中分别记录启动与关闭日志,并在回调执行过程中捕获并处理异常,确保异常不会导致Kit主进程崩溃。最终通过Kit日志输出验证扩展生命周期管理的正确性。

实现方案

创建一个标准的Omniverse Kit扩展,扩展名为lifecycle_manager。在extension.py中定义LifecycleManagerExtension类,继承自omni.ext.IExt。在on_startup中记录启动日志并模拟可能出现的异常场景(如配置文件缺失),通过try-except捕获后记录错误日志并继续执行;在on_shutdown中记录关闭日志,同样包含异常处理逻辑。扩展的config/extension.toml声明扩展元数据与入口。

Omniverse Kit 主进程 Extension Manager 加载/卸载扩展 LifecycleManagerExtension on_startup() 1. 记录启动日志 2. 模拟异常场景 3. try-except 捕获 4. 记录错误日志 on_shutdown() 1. 记录关闭日志 2. 清理资源 3. 异常捕获处理 4. 记录完成日志 Kit 日志输出 [INFO] LifecycleManager startup: begin [ERROR] config missing [WARN] fallback to default config [INFO] startup: done [INFO] LifecycleManager shutdown: begin [INFO] shutdown: done 加载 卸载 日志 日志

代码实现

创建扩展目录结构如下:

lifecycle_manager/
├── config/
│   └── extension.toml
└── lifecycle_manager/
    └── extension.py

config/extension.toml

[package]
version = "1.0.0"
title = "Lifecycle Manager"
description = "Demonstrates extension lifecycle management with logging and exception handling."

[dependencies]
omni.kit = "{}"

[[extensions]]
id = "lifecycle_manager"
version = "1.0.0"

lifecycle_manager/extension.py

import carb
import omni.ext
import os

class LifecycleManagerExtension(omni.ext.IExt):
    """扩展生命周期管理示例:在on_startup和on_shutdown中记录日志并处理异常。"""

    def __init__(self):
        super().__init__()
        self._config_path = os.path.join(os.path.dirname(__file__), "..", "config", "settings.json")
        self._initialized = False

    def on_startup(self, ext_id: str):
        """扩展启动时调用。记录启动日志,模拟并处理异常。"""
        carb.log_info(f"LifecycleManager startup: begin (ext_id={ext_id})")

        try:
            # 模拟可能失败的配置加载
            if not os.path.exists(self._config_path):
                raise FileNotFoundError(f"Config file not found: {self._config_path}")

            # 实际项目中在此加载配置
            carb.log_info("LifecycleManager startup: config loaded successfully")

        except FileNotFoundError as e:
            carb.log_error(f"LifecycleManager startup: {e}")
            carb.log_warn("LifecycleManager startup: falling back to default configuration")
            # 使用默认配置继续执行,不中断启动流程

        except Exception as e:
            carb.log_error(f"LifecycleManager startup: unexpected error - {e}")
            # 记录异常但继续启动,保证扩展可用

        self._initialized = True
        carb.log_info("LifecycleManager startup: done")

    def on_shutdown(self):
        """扩展关闭时调用。记录关闭日志,清理资源并处理异常。"""
        carb.log_info("LifecycleManager shutdown: begin")

        try:
            if not self._initialized:
                raise RuntimeError("Extension was not properly initialized")

            # 实际项目中在此释放资源、保存状态等
            carb.log_info("LifecycleManager shutdown: resources released")

        except RuntimeError as e:
            carb.log_error(f"LifecycleManager shutdown: {e}")
            # 即使状态异常也继续完成关闭流程

        except Exception as e:
            carb.log_error(f"LifecycleManager shutdown: unexpected error - {e}")

        finally:
            self._initialized = False
            carb.log_info("LifecycleManager shutdown: done")

落地与验证

运行方式:将lifecycle_manager目录放入Omniverse Kit的扩展搜索路径(如kit/exts),启动Kit时通过--enable lifecycle_manager参数加载扩展,或在Kit扩展管理器中手动启用。

验证步骤:

  1. 启动Kit并加载扩展,观察控制台或日志文件(kit.log)中应依次出现LifecycleManager startup: begin、LifecycleManager startup: config missing(错误日志)、LifecycleManager startup: falling back to default configuration(警告日志)以及LifecycleManager startup: done。
  2. 关闭Kit或禁用扩展,日志中应出现LifecycleManager shutdown: begin和LifecycleManager shutdown: done。
  3. 确认整个过程中Kit主进程未崩溃,扩展能正常加载与卸载。

判定标准:日志输出顺序与上述预期一致,且无未捕获异常导致Kit进程退出,即视为验证通过。由于settings.json文件未创建,启动时会触发FileNotFoundError,代码通过try-except捕获后记录错误并回退到默认配置,这正是本案例要演示的异常处理路径。