Find Unused Python Packages Automatically
Scan a Python project's source files for imports and list installed packages not imported anywhere.
Python code
40 linesimport pkg_resources
import ast
import os
import sys
from pathlib import Path
def find_imports_in_project(project_dir="."):
imports = set()
for py_file in Path(project_dir).rglob("*.py"):
try:
with open(py_file, "r") as f:
tree = ast.parse(f.read())
for node in ast.walk(tree):
if isinstance(node, ast.Import):
for alias in node.names:
imports.add(alias.name.split(".")[0])
elif isinstance(node, ast.ImportFrom):
if node.module:
imports.add(node.module.split(".")[0])
except (SyntaxError, UnicodeDecodeError):
pass
return imports
def get_installed_packages():
return {pkg.key for pkg in pkg_resources.working_set}
def find_unused_packages(project_dir="."):
installed = get_installed_packages()
used = find_imports_in_project(project_dir)
unused = installed - used
return sorted(unused)
if __name__ == "__main__":
unused = find_unused_packages()
if unused:
print("Unused packages found:")
for pkg in unused:
print(f" - {pkg}")
else:
print("No unused packages detected.")
Output
Unused packages found:
- requests
- numpy
- flask
How it works
The script uses pkg_resources.working_set to list all installed packages. It then parses every .py file in the project directory with the ast module, collecting top-level module names from import and from ... import statements. Only the base package name (before the first dot) is kept to match against installed package keys. The set difference between installed and used packages reveals which packages are potentially unnecessary. This is a static analysis approach and won't catch packages used via dynamic imports (importlib) or string-based imports.
Common mistakes
- Ignoring subpackages — only the top-level package name is collected, so `pandas.core` becomes just `pandas`.
- Not handling virtual environments — the script checks globally installed packages; run it inside the target environment's Python.
- Missing `__init__.py` imports — packages imported indirectly through package `__init__` files may be missed.
- Forgetting namespace packages — `pkg_resources` may not list them correctly in some setups.
Variations
- Use `importlib.metadata.distributions()` (Python 3.8+) instead of `pkg_resources`.
- Add a `--exclude` CLI option to skip known packages like `pip`, `setuptools`.
Real-world use cases
- Cleaning up a requirements.txt before deploying to production to reduce attack surface.
- Auditing dependency bloat in CI after merging a large feature branch.
- Documenting dead dependencies in legacy projects before a major refactor.
Sponsored
More from Automation & scripting
- Automatically Clean Temporary Files from Applications Using Python medium
- Automatically Download the Latest Software Release from GitHub with Python medium
- Automatically Generate Charts from CSV Files with One Command medium
- Automatically Generate Hardware Inventory Reports in Python easy
- Automatically Log CPU, RAM, and Disk Usage Every Minute in Python easy
- Batch Rename Hundreds of Files in Python easy
Keep learning
Related tutorials and quizzes for this topic.