ImportError: cannot import name 'X' from partially initialized module 'Y'

Python ImportError: Partial initialization from circular import

Programming & Dev Tools Intermediate 👁 1 views 📅 May 29, 2026

This error means you've got a circular import where two modules try to import each other at load time. The fix is to restructure code or use deferred imports.

When This Error Hits

You're building a Python project — maybe a Flask app, a Django model setup, or a data pipeline with several modules. You run your script and get this:

ImportError: cannot import name 'UserDAO' from partially initialized module 'dao' (most likely due to a circular import)

It usually happens when you start the app and the import chain hits a loop. Two files try to import each other at the top level, and Python can't finish loading either one.

What's Going On Under the Hood

Python loads modules in a specific order. When you write from dao import UserDAO at the top of service.py, Python runs dao.py from top to bottom. But if dao.py also does from service import some_function at the top, Python tries to load service.py — which is still in the middle of loading. That's the "partially initialized" bit. Python throws the error because the name you need doesn't exist yet.

This isn't a bug in Python. It's a design problem in your code. The real fix is to break the circular dependency.

The Fix: Step by Step

Step 1 — Find the Circular Import

Look at the traceback. It'll show two files importing from each other at the top level. Write down the exact lines. For example:

  • dao.py line 1: from service import format_user
  • service.py line 1: from dao import UserDAO

That's your loop. Both imports happen at module load time.

Step 2 — Move the Import Inside a Function

The quickest fix that doesn't require a full refactor: move the import into a function or method where it's actually used. So in dao.py, replace:

from service import format_user

def get_user():
    return format_user(user_data)

With:

def get_user():
    from service import format_user
    return format_user(user_data)

Now format_user is imported only when get_user() is called — not when dao.py loads. This breaks the circular dependency because service.py finishes loading first.

After applying this change, restart your app. The error should disappear.

Step 3 — Check for Side Effects

Sometimes a deferred import can cause a tiny performance hit if it's called in a tight loop. In most apps, it's fine. But if you're doing this in a hot code path, consider step 4 instead.

Step 4 — A Cleaner Fix: Extract a Common Module

The best long-term fix is to pull the shared code into a third module that neither dao.py nor service.py imports from. For example, create common.py with the format_user function. Then both dao.py and service.py import from common.py instead of each other. No circular import.

If you choose this route, update both files. Remove the line that imports from the other module, and add from common import format_user in both. Test immediately.

Step 5 — Use import Instead of from ... import

Sometimes you can get away with using import package.module and then referencing the attribute with full path. This won't fix all circular imports, but it can work if the dependency is only at the attribute level and not at module initialization. Try it if the deferred import feels too hacky for you. In dao.py, replace:

from service import format_user

With:

import service
# Then use service.format_user(...)

This delays the attribute lookup until runtime. But if service also imports dao at the top, you'll just run into the same problem. So test it.

What If It Still Fails?

If the error persists after trying the fixes above, here's what to check:

  • Look for hidden imports inside __init__.py files. A lot of circular imports sneak in through package __init__.py files that import submodules eagerly. Move those imports inside functions too, or restructure the package so that __init__.py doesn't load everything at once.
  • Check third-party libraries. Sometimes you're not calling the import directly, but a library you use has its own circular dependency. Update your packages with pip install --upgrade. If that doesn't help, check the library's issue tracker.
  • Use python -v to trace module loading. Run python -v your_script.py. You'll see the order Python loads modules. Look for a sequence where module A starts loading, then B starts loading before A finishes. That's your loop.
  • Refactor to a flat structure. If you're deep in dependency hell, consider merging the two modules into one file. Not elegant, but it works.

Circular imports are a design smell, not a terminal illness. Once you spot the pattern, they're easy to fix. Stick with deferred imports for a quick win, or extract shared logic for a cleaner solution.

Was this solution helpful?