# Python "cannot import name X from partially initialized module" (Circular)

> Fix "ImportError: cannot import name X from partially initialized module (most likely due to a circular import)" in CI - break the import cycle.

Source: https://latchkey.dev/learn/python/py-importerror-partially-initialized-circular  
Updated: 2026-06-25

Two modules import each other at load time, so when one is half-defined the other tries to use a name that does not exist yet. The "partially initialized module" wording is the unmistakable signature of a circular import.

## Diagnose it: which Python, and which index?

A pip failure in CI is usually about the interpreter or the index rather than the package. Runners have several Pythons installed, and the one on PATH is not necessarily the one your virtualenv or your workflow selected.

```Terminal
which -a python python3 pip pip3
python -c "import sys; print(sys.executable, sys.version)"
pip config list
pip debug --verbose 2>/dev/null | grep -i "compatible tags" | head -5
```

> Compatible tags decide whether a wheel is usable. A package that installs from a wheel on your machine and builds from source in CI is a tag mismatch, and the resulting failure is a compiler error rather than a pip error.

## FAQ

### What causes Python "cannot import name X from partially initialized module" (Circular)?

There are 2 common causes: two modules import each other at module scope and a shared object defined in a module that imports back. Module A imports B at the top, B imports A at the top.

### How do I fix Python "cannot import name X from partially initialized module" (Circular)?

There are 2 fixes depending on which cause you have: move the shared symbol to a neutral module and defer the import inside the function. Work through them in order, since the first is the most common.

### What does Python "cannot import name X from partially initialized module" (Circular) actually mean?

An import fails with ImportError: cannot import name X from partially initialized module Y (most likely due to a circular import), naming the file still being initialized.

### How do I stop Python "cannot import name X from partially initialized module" (Circular) happening again?

Keep shared objects in a leaf module that imports nothing back. The prevention section lists 3 changes that keep it from recurring.

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
