Python "ImportError: cannot import name" — Circular Imports and Shadowing

The module imported, but the name you asked for isn't there yet — circular imports are the headline cause, followed by stale bytecode, shadowing a stdlib/package name, and version drift.

What you'll see

Root causes

Circular import (the classic)

a.py imports from b.py while b.py imports from a.py; at the moment of import, the needed name isn't defined yet. The traceback's 'partially initialized module' wording confirms it.

Name shadowing or a different package on path

Your email.py shadows stdlib, or pip installed another version elsewhere and sys.path picks it first. python -c 'import module; print(module.__file__)' names the file actually loaded.

Version drift: the name exists only in a newer release

Docs say feature X exists, your pinned package doesn't have it yet (or renamed it). pip show <pkg> plus a grep of the installed source settles it.

Fix it

  1. Identify the file actually being imported
    python -c "import <module> as m; print(m.__file__)"
  2. Break the cycle: move shared code to a third module or import inside the function
    # circular fix: extract shared symbols to common.py, or defer: def f(): from b import X  (import at call time)
  3. Clear stale bytecode after renames
    find . -name '__pycache__' -type d -exec rm -rf {} + 2>/dev/null; find . -name '*.pyc' -delete
  4. Check the installed version for the symbol
    python -c "import pkg; print(pkg.__version__)" ; grep -r "class X\|def X" $(python -c "import pkg,os; print(os.path.dirname(pkg.__file__))") | head -3

Field note

If the error mentions 'most likely due to a circular import', it's literally telling you the fix. Naming files after stdlib modules (email.py, json.py, typing.py) creates this exact error in imports far away from the culprit.

Common questions

Why does the import work when I run a different script?

Import order differs by entry point: circular imports only fail when the cycle is entered in the wrong state. The reliable fix is breaking the cycle, not choosing a lucky entry point.

How do I find which file shadows a stdlib module?

python -c 'import email; print(email.__file__)' — a path inside your project (instead of the stdlib location) is the shadow. Rename your file.

Ship it right the first time

Our most-documented failures, packaged as ready-to-ship starter kits: Docker, Kubernetes, and Terraform.

Browse the template store →

One-time. Yours to modify. Instant download from the NinjaOps template store.