A production-ready Python import cleaner that detects and removes unused imports while preserving code behavior.
Project description
importclean
A production-ready Python import cleaner. Detect and safely remove unused imports from an entire project while preserving code behavior, formatting, and style.
Features
- AST + LibCST analysis - detects every import variant without reformatting unrelated code
- Safe by default - never removes conditional,
TYPE_CHECKING,try/except, or star imports - Partial cleanup - removes only unused names from
from x import a, b, c - Alias detection -
import numpy as npis kept whennpis used - Duplicate removal - collapses repeated identical import statements
- Circular import detection - finds cycles across the whole project
- Dependency graph - renders ASCII trees and Graphviz
.dotfiles - Heavy import suggestions - recommends lazy imports for expensive modules
- Import sorting - PEP 8 / isort-compatible grouping
- Post-clean validation - every modified file is re-parsed and compiled; originals are restored on failure
- Multiprocessing - scales to thousands of files
- Plugin system - add custom rules for project-specific policies
.importclean.tomlconfiguration
Installation
pip install importclean
For development:
git clone https://github.com/Madhav703/importclean
cd importclean
pip install -e ".[dev]"
Quick Start
CLI
importclean .
importclean . --dry-run
importclean . --check
# Show unified diffs
importclean . --diff
# Print import dependency graph
importclean . --graph
# Output results as JSON
importclean . --json
# Print statistics only
importclean . --stats
# Verify all files are syntactically valid
importclean . --verify
# Sort imports in PEP 8 order
importclean . --sort
# Write dependency graph as Graphviz .dot
importclean . --dot graph.dot
# Clean a single file
importclean myfile.py
# Verbose output (per-file details)
importclean . -v
Python API
from importclean import clean_project, clean_file
# Clean an entire project (dry run)
report = clean_project(
path=".",
dry_run=True,
safe_mode=True,
)
print(report.summary())
# Clean a single file
file_report = clean_file("src/mymodule.py", dry_run=False)
print(f"Removed {len(file_report.unused)} unused imports")
Configuration
Create .importclean.toml in your project root:
ignore = [
".venv",
"tests",
"migrations",
]
safe_mode = true
sort_imports = true
remove_unused = true
workers = 4
Safety Guarantees
importclean will never:
- Remove an import that is actually used
- Remove star imports (
from x import *) - Remove
__future__imports - Remove
TYPE_CHECKING-guarded imports - Remove
try/except-wrapped imports - Save a file that fails
ast.parse()orcompile()after transformation - Alter any code outside of import statements
If post-clean validation fails, the original file is restored automatically and the error is reported.
What Gets Removed
| Pattern | Behavior |
|---|---|
import os (unused) |
Removed |
import os (used) |
Kept |
import numpy as np + np.array(...) |
Kept |
from os import path, mkdir (only path used) |
mkdir removed |
from os.path import * |
Never removed |
Duplicate import os |
Second occurrence removed |
if TYPE_CHECKING: from x import T |
Never removed |
try: import ujson as json |
Never removed |
Plugin System
import ast
from typing import Optional
from importclean import clean_project
from importclean.models import ImportInfo
from importclean.plugins.base import BaseRule, RuleResult
from importclean.plugins.registry import PluginRegistry
class NoPickleRule(BaseRule):
name = "no-pickle"
def check(self, node: ImportInfo, tree: ast.Module) -> Optional[RuleResult]:
if node.module == "pickle":
return RuleResult(
import_info=node,
message="Prefer json or msgpack over pickle.",
should_remove=False,
)
return None
registry = PluginRegistry()
registry.register(NoPickleRule)
report = clean_project(".", dry_run=True, registry=registry)
Development
# Run tests
pytest
# Run tests with coverage
pytest --cov=importclean --cov-report=term-missing
# Lint
ruff check importclean tests
# Type check
mypy importclean
# Format
black importclean tests
License
MIT - see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file importclean-0.1.0.tar.gz.
File metadata
- Download URL: importclean-0.1.0.tar.gz
- Upload date:
- Size: 26.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fbfca8b21d4eb944f2faa58c189e71c28768686cd4514f233e6d4b6ffce57a60
|
|
| MD5 |
efacdf608fb355c0e7d9383b6cd03296
|
|
| BLAKE2b-256 |
e548da17a47364dcfdcaf24507295a1752bc5dbb161fc97913d015c6efdb3785
|
File details
Details for the file importclean-0.1.0-py3-none-any.whl.
File metadata
- Download URL: importclean-0.1.0-py3-none-any.whl
- Upload date:
- Size: 33.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1c7856a67c1b2810a55b7882702cadb31ab2e873a21856bbb67269395d2bd5ff
|
|
| MD5 |
28d63e50e016bab5872f7ac471550b26
|
|
| BLAKE2b-256 |
737e246198b7770f72e1a5b960248ce74a41b50b187cc85636214fdf629b8175
|