A static analysis tool for Python codebases written in Python (formerly was written in Rust but we ditched that) that detects unreachable functions and unused imports, aka dead code. Faster and better results than many alternatives like Flake8 and Pylint, and finding more dead code than Vulture in our tests with comparable speed.
- Unused Functions & Methods: Finds functions and methods that are never called
- Unused Classes: Detects classes that are never instantiated or inherited
- Unused Imports: Identifies imports that serve no purpose
- Cross-Module Tracking: Analyzes usage patterns across your entire codebase
The benchmark checks how well static analysis tools spot dead code in Python. Things such as unused functions, classes, imports, variables, that kinda stuff. To read more refer down below.
The methodology and process for benchmarking can be found in BENCHMARK.md
Skylos (Local Dev) | 0.013 | 34 | 22 | 12 | 7 | 0.6471 | 0.7586 | 0.6984 |
Vulture (0%) | 0.054 | 32 | 11 | 20 | 18 | 0.3548 | 0.3793 | 0.3667 |
Vulture (60%) | 0.044 | 32 | 11 | 20 | 18 | 0.3548 | 0.3793 | 0.3667 |
Flake8 | 0.371 | 16 | 5 | 7 | 24 | 0.4167 | 0.1724 | 0.2439 |
Pylint | 0.705 | 11 | 0 | 8 | 29 | 0.0000 | 0.0000 | 0.0000 |
Ruff | 0.140 | 16 | 5 | 7 | 24 | 0.4167 | 0.1724 | 0.2439 |
To run the benchmark: python compare_tools.py /path/to/sample_repo
Note: More can be found in BENCHMARK.md
The interactive mode lets you select specific functions and imports to remove:
- Select items: Use arrow keys and space to select/deselect
- Confirm changes: Review selected items before applying
- Auto-cleanup: Files are automatically updated
- Python ≥3.9
- pytest
- inquirer
Q: Why doesn't Skylos find 100% of dead code? A: Python's dynamic features (getattr, globals, etc.) can't be perfectly analyzed statically. No tool can achieve 100% accuracy. If they say they can, they're lying.
Q: Why are the results different on my codebase? A: These benchmarks use specific test cases. Your code patterns (frameworks, legacy code, etc.) will give different results.
Q: Are these benchmarks realistic? A: They test common scenarios but can't cover every edge case. Use them as a guide, not gospel.
Q: Should I automatically delete everything flagged as unused? A: No. Always review results manually, especially for framework code, APIs, and test utilities.
Q: Why did Ruff underperform? A: Like all other tools, Ruff is focused on detecting specific, surface-level issues. Tools like Vulture and Skylos are built SPECIFICALLY for dead code detection. It is NOT a specialized dead code detector. If your goal is dead code, then ruff is the wrong tool. It is a good tool but it's like using a wrench to hammer a nail. Good tool, wrong purpose.
- Dynamic code: getattr(), globals(), runtime imports are hard to detect
- Frameworks: Django models, Flask routes may appear unused but aren't
- Test data: Limited scenarios, your mileage may vary
- False positives: Always manually review before deleting code
If we can detect 100% of all dead code in any structure, we wouldn't be sitting here. But we definitely tried our best
-
Permission Errors
Error: Permission denied when removing functionCheck file permissions before running in interactive mode.
-
Missing Dependencies
Interactive mode requires 'inquirer' packageInstall with: pip install skylos[interactive]
We welcome contributions! Please read our Contributing Guidelines before submitting pull requests.
- Fork the repository
- Create a feature branch (git checkout -b feature/amazing-feature)
- Commit your changes (git commit -m 'Add amazing feature')
- Push to the branch (git push origin feature/amazing-feature)
- Open a Pull Request
- Add a production flag, to include dead codes that are used in test but not in the actual execution
- Expand our test cases
- Configuration file support
- Custom analysis rules
- Git hooks integration
- CI/CD integration examples
- Web interface
- Support for other languages
- Further optimization
This project is licensed under the Apache 2.0 License - see the LICENSE file for details.
- Author: oha
- Email: [email protected]
- GitHub: @duriantaco