Skip to main content

importclean

A production-ready Python import cleaner. Detect and safely remove unused imports from an entire project while preserving code behavior, formatting, and style.

PyPI Python License: MIT CI Coverage

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 np is kept when np is used
  • Duplicate removal - collapses repeated identical import statements
  • Circular import detection - finds cycles across the whole project
  • Dependency graph - renders ASCII trees and Graphviz .dot files
  • 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.toml configuration

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() or compile() 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.

Release files for importclean 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for importclean 0.1.0
File Size Uploaded
importclean-0.1.0.tar.gz 26.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for importclean 0.1.0
File Interpreter ABI Platform
importclean-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 60.0 kB

Release files / importclean-0.1.0.tar.gz

Download URL importclean-0.1.0.tar.gz
Size 26.8 kB
Tags Source
SHA-256 checksum
How to use checksums
fbfca8b21d4eb944f2faa58c189e71c28768686cd4514f233e6d4b6ffce57a60
BLAKE2b-256 checksum
How to use checksums
e548da17a47364dcfdcaf24507295a1752bc5dbb161fc97913d015c6efdb3785
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release files / importclean-0.1.0-py3-none-any.whl

Download URL importclean-0.1.0-py3-none-any.whl
Size 33.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1c7856a67c1b2810a55b7882702cadb31ab2e873a21856bbb67269395d2bd5ff
BLAKE2b-256 checksum
How to use checksums
737e246198b7770f72e1a5b960248ce74a41b50b187cc85636214fdf629b8175
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page