Skip to main content

Detect and visualize circular imports in Python projects.

Project description

knot

CI Python License: MIT PyPI

Detect and visualize circular imports in Python projects — fast, static, and dependency-free.

Circular imports are a common source of ImportError and "partially initialized module" failures, and they quietly couple your code together. knot finds them without importing or running a single line of your project: it parses the source with the standard-library ast module, builds the internal module dependency graph, and reports every cycle with a concrete example path.

It has zero runtime dependencies, runs in CI (non-zero exit on cycles), and can emit a Mermaid diagram of your import graph.

Demo

knot detecting a circular import in the bundled example project

The examples/shop package intentionally contains a circular import so you can try knot immediately: knot examples/shop.

Installation

pip install knot-imports

Or run from a checkout without installing:

PYTHONPATH=src python -m knot path/to/project

Usage

# Analyze the current directory
knot .

# Analyze a specific package or project
knot path/to/your_package

# Exclude directories (repeatable); common ones are skipped by default
knot . --exclude migrations --exclude examples

Example

Given a package where order and customer import each other:

$ knot shop
Analyzed 3 modules, 3 internal imports.
Found 1 import cycle:

  1. shop.customer -> shop.order -> shop.customer

Output formats

--format text (default), json, or mermaid:

knot . --format json      # machine-readable: summary, cycles, full graph
knot . --format mermaid   # a graph LR diagram with cycle nodes highlighted

The Mermaid output pastes directly into a GitHub Markdown ```mermaid block or the Mermaid Live Editor.

Exit codes

Code Meaning
0 No cycles found
1 One or more cycles found
2 Error (e.g. path not found)

Pass --no-fail to always exit 0 (useful when you only want the report). Drop knot . into a pre-commit hook or CI step to keep cycles out of main.

How it works

  1. Discover every .py file under the target and map it to its fully-qualified module name, mirroring how Python would import it.
  2. Parse each file with ast and resolve import / from ... import statements (absolute and relative) to internal modules; external imports are ignored.
  3. Detect cycles by computing strongly connected components with an iterative implementation of Tarjan's algorithm (safe on very large graphs), then extract a concrete example path for each cycle.

Development

git clone https://github.com/gazzycodes/knot
cd knot
PYTHONPATH=src python -m unittest discover -s tests -v

The demo GIF is regenerated with python make_demo.py (requires pillow).

Contributions are welcome — please open an issue or PR.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

knot_imports-0.1.0.tar.gz (84.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

knot_imports-0.1.0-py3-none-any.whl (11.6 kB view details)

Uploaded Python 3

File details

Details for the file knot_imports-0.1.0.tar.gz.

File metadata

  • Download URL: knot_imports-0.1.0.tar.gz
  • Upload date:
  • Size: 84.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for knot_imports-0.1.0.tar.gz
Algorithm Hash digest
SHA256 0c02a71f7c34d44eb2dd7507840beae4b8b764c270cc6676e1808dc34372a1ce
MD5 1c32937fb80c405305bd59afd681555d
BLAKE2b-256 5d0092e17f7377058f50b128820befa1e9726129a42402b7f221245c5a1de757

See more details on using hashes here.

File details

Details for the file knot_imports-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: knot_imports-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 11.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for knot_imports-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6eefe68afb4ad84f43594d173b9c671e6987a05ee4d53b498e42c0793942c3dc
MD5 9935105657aba371f31257ba656626dc
BLAKE2b-256 677214d374f2cf1c70a090615373d413679f11b8b383bda4a5ce7ce55cae8580

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page