How-ToFebruary 9, 20264 min read

How to Find Dead Code in Python with Vulture

Vulture detects unused Python code using AST analysis. Learn how to install it, tune confidence thresholds, handle false positives, and integrate with CleanAI.

pythonvulturedead-codecode-cleanupast

Python's dynamic nature makes dead code detection harder than in statically-typed languages. Functions can be called via getattr(), classes instantiated from strings, and modules imported dynamically. Vulture handles this by using AST analysis with confidence scoring.

What Vulture Detects

Vulture parses Python files into abstract syntax trees and reports:

  • Unused functions -- defined with def but never called
  • Unused classes -- defined with class but never instantiated or subclassed
  • Unused imports -- import or from ... import statements where the imported name is never used
  • Unused variables -- assigned but never read
  • Unused properties -- class attributes that are never accessed
  • Unreachable code -- code after return, break, continue, or raise statements

Installing Vulture

pip install vulture

Running a Scan

Basic usage:

vulture src/

With confidence threshold (recommended):

vulture src/ --min-confidence 80

The --min-confidence flag filters out findings where Vulture is less certain the code is truly unused. A threshold of 80 is a good starting point -- it catches obvious dead code while filtering most false positives.

Understanding Confidence Scores

Vulture assigns a confidence percentage to each finding:

  • 100% -- definitely unused (e.g., a function defined in a module that is never imported)
  • 60-90% -- likely unused but could be called dynamically
  • Below 60% -- might be used via dynamic patterns
src/utils/legacy.py:15: unused function 'calculate_discount' (confidence: 100%)
src/models/user.py:42: unused variable 'cache_key' (confidence: 90%)
src/api/handlers.py:8: unused import 'json' (confidence: 60%)

Start with --min-confidence 80 and lower it as you get comfortable with the tool.

Handling False Positives

Python's dynamic features cause specific false positive patterns:

Django/Flask URL Routing

View functions referenced in URL patterns are not directly imported:

# urls.py
urlpatterns = [
    path("users/", views.user_list),  # Vulture sees this as a reference
]

# But if the view is in a different file and only referenced by string:
path("api/users/", "myapp.views.user_list"),  # Vulture cannot trace this

Decorators and Metaclasses

@app.route("/api/health")  # Vulture may not trace the decorator's registration
def health_check():
    return {"status": "ok"}

Dynamic Attribute Access

handler_name = f"handle_{event_type}"
handler = getattr(self, handler_name)  # Vulture cannot trace this
handler()

Creating a Whitelist

For known false positives, create a whitelist file:

# whitelist.py
# These are used dynamically and should not be flagged

# Django views referenced by URL strings
user_list  # noqa
user_detail  # noqa

# Signal handlers
on_user_created  # noqa

Run Vulture with the whitelist:

vulture src/ whitelist.py --min-confidence 80

Using Vulture with CleanAI

CleanAI integrates Vulture for Python projects:

  1. Open your Python project in VS Code or Cursor
  2. Run "CleanAI: Analyze Codebase"
  3. CleanAI detects Python files and runs Vulture
  4. Results appear in the webview panel with confidence scores
  5. Remove findings one-by-one or use Auto Clean (Safe)

CleanAI filters low-confidence findings by default and lets you adjust the threshold in settings.

CI Integration

Add Vulture to your CI pipeline:

vulture src/ whitelist.py --min-confidence 80

The command exits with code 1 if any findings are detected, failing the CI check.

Best Practices

  1. Start with high confidence -- use --min-confidence 90 initially, then lower as you clean up
  2. Maintain a whitelist -- add legitimate dynamic patterns to avoid repeated false positives
  3. Scan regularly -- Python dead code accumulates quickly in large projects
  4. Combine with type hints -- typed Python code produces fewer false positives because Vulture can trace references more accurately

Getting Started

Install Vulture (pip install vulture) for command-line scanning, or install CleanAI for visual scanning with safe removal in VS Code and Cursor.