mcpField
P
py-code-health

py-code-health

github.com/l-mb开发5672 次安装34 周前更新
代码仓库

关于 py-code-health

py-code-health 是面向 Python 代码库维护的技能,用于发现高置信度的死代码和重复代码,并指导清理与合并。它使用 vulture 和 pylint,同时强调核实误报并在修改后运行测试。

主要功能

  1. 01使用 vulture 检测未使用代码
  2. 02用置信度筛选并排序结果
  3. 03使用 pylint 查找重复代码
  4. 04合并重复逻辑并参数化函数
  5. 05识别误报并通过白名单处理
  6. 06清理注释代码并验证测试

适用场景

  1. 01清理确认未使用的函数和导入
  2. 02查找多个文件中的重复代码
  3. 03重构相似逻辑以减少重复
  4. 04删除代码后验证测试与覆盖率

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/l-mb/python-refactoring-skills --skill py-code-health

安装后在 Claude Code 中输入/py-code-health确认已加载。

详细介绍

Python 代码健康维护

删除无用代码并整合重复内容,让代码库保持整洁且易于维护。

目标

  1. 检测未使用的代码(函数、类、变量)
  2. 高置信度地查找并删除无用代码
  3. 识别文件之间的重复代码
  4. 将相似代码整合到参数化函数中
  5. 删除多余的导入和注释掉的代码

所需工具

添加到 [dependency-groups] dev:"vulture"、"pylint"

  • vulture:基于 AST 的无用代码检测
  • pylint:重复代码检测

权限:先运行 py-quality-setup,配置 .claude/settings.local.json 并授予所有所需工具权限。

无用代码检测

查找未使用的代码
# Using vulture (primary tool)
vulture .                              # Find all unused code
vulture . --min-confidence 80          # High confidence only
vulture . --min-confidence 80 --sort-by-size  # Largest dead code first
vulture . --exclude=tests/,venv/,.venv/ # Exclude directories

# Generate report
vulture . --min-confidence 80 > dead_code_report.txt
解读 Vulture 输出
unused function 'calculate_tax' (80% confidence)
src/billing.py:45

unused class 'LegacyProcessor' (90% confidence)
src/processors.py:123

unused variable 'debug_mode' (60% confidence)
src/config.py:12

置信度级别:

  • 60-70%:可能是误报(动态导入、元类等)
  • 80-89%:很可能未使用,删除前请验证
  • 90-100%:几乎可以确定未使用
处理误报

Vulture 可能会标记实际上正在使用的代码:

1. 动态导入/调用:

# Flagged as unused but called dynamically
def plugin_handler():
    pass

# Called via: getattr(module, 'plugin_handler')()

2. 框架约定:

# Django models - fields used by ORM
class User(models.Model):
    email = models.EmailField()  # May be flagged but used by Django

3. 公共 API:

# Part of library's public API, used by external code
def public_function():
    pass

解决方案:

  • 添加到白名单文件:vulture . whitelist.py
  • 添加注释:# pragma: no cover 或自定义标记
  • 接受公共 API 的误报
  1. 应该使用但尚未使用的代码:

例如,常量、魔术数字、类型定义,甚至函数都可能看起来未被使用。但这实际上可能就是问题所在!(考虑是否存在未完成的重构或其他原因。)

删除看似无用的代码之前,请确认是否存在应该引用它的相似模式。如果存在,请改为修复调用/使用位置。

删除无用代码
# BEFORE - Unused functions cluttering codebase
def old_calculate_price(item):  # Last used 2 years ago
    return item.cost * 1.1

def deprecated_handler(data):  # Replaced by new_handler
    pass

# AFTER - Clean, only active code remains
# (Dead code completely removed)

重复代码检测

查找重复内容
# Using pylint (detects similar code blocks)
pylint --disable=all --enable=duplicate-code --recursive=y .

# Configure minimum similar lines (default: 4)
pylint --disable=all --enable=duplicate-code --duplicate-code-min-lines=6 --recursive=y .

# JSON output for parsing
pylint --disable=all --enable=duplicate-code --output-format=json --recursive=y . > duplication.json
解读 Pylint 输出
Similar lines in 2 files
src/auth.py:45-60
src/admin.py:123-138

def validate_credentials(username, password):
    if not username or not password:
        return False
    user = db.get_user(username)
    if not user:
        return False
    return check_password(password, user.password_hash)

整合模式

参数化相似函数
# BEFORE - Duplicate code with slight variations
def process_user(data: dict) -> User:
    if not data.get("email"):
        raise ValueError("Missing email")
    if not data.get("name"):
        raise ValueError("Missing name")
    return User(email=data["email"], name=data["name"])

def process_admin(data: dict) -> Admin:
    if not data.get("email"):
        raise ValueError("Missing email")
    if not data.get("name"):
        raise ValueError("Missing name")
    return Admin(email=data["email"], name=data["name"])

# AFTER - Single parametrized function
T = TypeVar('T', User, Admin)

def process_entity(data: dict, entity_class: type[T]) -> T:
    if not data.get("email"):
        raise ValueError("Missing email")
    if not data.get("name"):
        raise ValueError("Missing name")
    return entity_class(email=data["email"], name=data["name"])

# Usage
user = process_entity(data, User)
admin = process_entity(data, Admin)
提取通用逻辑
# BEFORE - Duplicated validation in multiple functions
def create_user(email: str, age: int) -> User:
    if not email or "@" not in email:
        raise ValueError("Invalid email")
    if age < 0 or age > 150:
        raise ValueError("Invalid age")
    return User(email=email, age=age)

def update_user(user_id: int, email: str, age: int) -> User:
    if not email or "@" not in email:
        raise ValueError("Invalid email")
    if age < 0 or age > 150:
        raise ValueError("Invalid age")
    user = get_user(user_id)
    user.email = email
    user.age = age
    return user

# AFTER - Extract common validation
def validate_email(email: str) -> None:
    if not email or "@" not in email:
        raise ValueError("Invalid email")

def validate_age(age: int) -> None:
    if age < 0 or age > 150:
        raise ValueError("Invalid age")

def create_user(email: str, age: int) -> User:
    validate_email(email)
    validate_age(age)
    return User(email=email, age=age)

def update_user(user_id: int, email: str, age: int) -> User:
    validate_email(email)
    validate_age(age)
    user = get_user(user_id)
    user.email = email
    user.age = age
    return user
使用配置而不是重复代码
# BEFORE - Similar handlers with different values
def process_csv_file(path: str) -> list:
    return parse_file(path, delimiter=",", encoding="utf-8", skip_header=True)

def process_tsv_file(path: str) -> list:
    return parse_file(path, delimiter="\t", encoding="utf-8", skip_header=True)

def process_psv_file(path: str) -> list:
    return parse_file(path, delimiter="|", encoding="utf-8", skip_header=True)

# AFTER - Configuration-driven
FILE_CONFIGS = {
    "csv": {"delimiter": ",", "encoding": "utf-8", "skip_header": True},
    "tsv": {"delimiter": "\t", "encoding": "utf-8", "skip_header": True},
    "psv": {"delimiter": "|", "encoding": "utf-8", "skip_header": True},
}

def process_file(path: str, file_type: str) -> list:
    config = FILE_CONFIGS[file_type]
    return parse_file(path, **config)

删除注释掉的代码

注释掉的代码也是一种无用代码:

# BEFORE - Cluttered with old code
def calculate_total(items: list) -> float:
    # Old implementation - kept for reference
    # total = 0
    # for item in items:
    #     total += item.price * item.quantity
    # return total

    # Another old version
    # return sum(item.price * item.quantity for item in items)

    # Current implementation
    return sum(item.total_price() for item in items)

# AFTER - Clean, rely on git history
def calculate_total(items: list) -> float:
    return sum(item.total_price() for item in items)

理由:Git 历史会保留旧实现。注释掉的代码会造成干扰。

验证清单

  • vulture . --min-confidence 80 未报告无用代码(或仅报告已接受的误报)
  • pylint --disable=all --enable=duplicate-code 未报告超过 6 行的重复代码块
  • 不再有注释掉的代码块
  • 删除代码后所有测试均通过
  • 代码覆盖率保持不变或有所提高
  • 已为有意保留的误报创建白名单文件(如有需要)

示例

示例:代码健康清理工作流

1. Scan: vulture . --min-confidence 80; pylint --disable=all --enable=duplicate-code --recursive=y .
2. Found: 5 unused functions (67 lines), 3 duplicate blocks (45 lines)
3. Remove: Verify unused code with Explore agent, delete confirmed dead code
4. Consolidate: Extract duplicates to shared utilities
5. Result: -112 lines total, tests pass, coverage improved to 86%

示例:处理误报

1. Scan: vulture . --min-confidence 80
2. Found: public_api_function flagged as unused (actually part of library API)
3. Create whitelist.py with: public_api_function  # Used by external consumers
4. Re-scan: vulture . whitelist.py --min-confidence 80
5. Result: False positive suppressed, real dead code still detected

示例:整合重复的验证逻辑

1. Scan: pylint --disable=all --enable=duplicate-code --recursive=y .
2. Found: Same validation logic in create_user() and update_user()
3. Extract: Create validate_user_data() helper function
4. Update: Both functions now call validate_user_data()
5. Result: -15 lines, single source of truth for validation

相关技能

  • 前置条件:py-quality-setup(工具配置)、py-test-quality(删除代码前的安全保障)
  • 后续步骤:py-complexity(清理后降低复杂度)
  • 另请参阅:py-security(重大更改前检查安全性)

评论

支持 Markdown