# PR #25437 完整报告

- 仓库：`sgl-project/sglang`
- 标题：Drop dead hasattr guards (hisparse_coordinator, metrics_collector)
- 合并时间：2026-05-16 09:19
- 原文链接：http://prhub.com.cn/sgl-project/sglang/pull/25437

---

# 执行摘要

- 一句话：删除两个冗余的 hasattr 守卫语句
- 推荐动作：可以直接合并的低风险机械重构。适合作为机械重构链中的一环，展示了如何安全地淘汰防御性编程遗迹。值得精读 PR body 的分析方法——通过追溯属性赋值点来证明守卫无效。

# 功能与动机

PR body 明确指出这两个 `hasattr` 守卫是死代码——`ModelRunner.__init__` 已在构造函数中无条件设置 `self.hisparse_coordinator = None`，`Scheduler.__init__` 在 `enable_metrics` 分支内创建 `self.metrics_collector`。守卫掩盖了真实的不变式，移除后若未来重构遗漏属性赋值，会立即在调用点抛出 `AttributeError` 而非静默失败。

# 实现拆解

1. **删除 `model_runner.py` 中的死守卫**：移除 `__init__` 末尾的 `if not hasattr(self, "hisparse_coordinator"): self.hisparse_coordinator = None` 块。该代码位于构造函数后续逻辑之后，而构造函数早前已无条件执行 `self.hisparse_coordinator = None`（见 `__init__` 中 `# For weight updates` 之前的部分），因此守卫始终为假。
2. **简化 `scheduler.py` 中的条件**：将 `if self.enable_metrics and hasattr(self, "metrics_collector"):` 改为 `if self.enable_metrics:`。`Scheduler.__init__` 在 `if self.enable_metrics:` 分支内创建 `self.metrics_collector`，后续执行路径一致，`hasattr` 检查冗余。
3. **无测试、配置或部署配套改动**：这是一个纯机械重构，删除死代码，不影响外部行为。

关键文件：
- `python/sglang/srt/model_executor/model_runner.py`（模块 模型加载器；类别 source；类型 data-contract）: 删除了 `if not hasattr(self, "hisparse_coordinator"): self.hisparse_coordinator = None` 死守卫，移除 3 行。
- `python/sglang/srt/managers/scheduler.py`（模块 调度器；类别 source；类型 core-logic）: 简化了 `if self.enable_metrics and hasattr(self, "metrics_collector"):` 为 `if self.enable_metrics:`，因为 `metrics_collector` 在 `enable_metrics` 分支内保证已创建。

关键符号：未识别

## 关键源码片段

### `python/sglang/srt/model_executor/model_runner.py`

删除了 `if not hasattr(self, "hisparse_coordinator"): self.hisparse_coordinator = None` 死守卫，移除 3 行。

```python
# python/sglang/srt/model_executor/model_runner.py
# 在 __init__ 末尾，原来有以下死守卫：
# if not hasattr(self, "hisparse_coordinator"):
# self.hisparse_coordinator = None
# 但构造函数中早有无条件赋值：
# self.hisparse_coordinator = None （大约在第 520 行前后）
# 因此这个守卫永远不会触发，现已删除。

```

### `python/sglang/srt/managers/scheduler.py`

简化了 `if self.enable_metrics and hasattr(self, "metrics_collector"):` 为 `if self.enable_metrics:`，因为 `metrics_collector` 在 `enable_metrics` 分支内保证已创建。

```python
# python/sglang/srt/managers/scheduler.py
# 在 init_model_worker 方法中，原来第 784 行：
# if self.enable_metrics and hasattr(self, "metrics_collector"):
# 改为：
if self.enable_metrics:
    self.metrics_collector.emit_constants(
        max_total_num_tokens=self.max_total_num_tokens,
        max_running_requests_under_SLO=getattr(
            self, "max_running_requests_under_SLO", None
        ),
        engine_startup_time=0.0,
        engine_load_weights_time=0.0,
        page_size=self.page_size,
        num_pages=self.max_total_num_tokens // self.page_size,
        context_len=self.model_config.context_len,
        startup_available_gpu_memory_gb=avail_mem,
    )
# 因为 Scheduler.__init__ 在 self.enable_metrics 为真时一定创建了
# self.metrics_collector，所以 hasattr 是多余的。

```

# 评论区精华

PR 没有 review 评论或线程；机器人注释提示达到每日配额限制。PR body 已完整说明每个守卫为何是死亡代码，且有同类 PR 的信任度作为背景（作者 fzyzcjy 正在批量做机械重构）。

- 暂无高价值评论线程

# 风险与影响

- 风险：风险极低：两处守卫均被证明为死代码，移除后仅在极端情况下（若未来有人误删了构造函数中的属性赋值）才会导致 `AttributeError`，而这正是期望的快速失败行为。不影响运行时逻辑、性能或兼容性。
- 影响：仅影响两个源文件，总共删除了 4 行、增加了 1 行（调整缩进）。对用户无感知；对开发者而言，未来若遗漏 `hisparse_coordinator` 或 `metrics_collector` 的初始化，将在调用点立即得到清晰的崩溃，而非静默跳过。
- 风险标记：无显著风险

# 关联脉络

- PR #25441 Annotate dead max_running_requests_under_SLO: 同一作者的同类机械重构，处理同一模块中的死代码问题。
- PR #25442 Lift forward_ct/cur_batch and use direct access in watchdog: 同属机械重构链，移除另一处防御性 getattr。
- PR #25444 Bundle Scheduler rank/size fields into a frozen ParallelState: 将调度器多个 rank/size 字段封装为值对象，属于更大的重构上下文。