Fundamentals 4 min read

How to Avoid Circular Imports in Python Code

This article explains why circular imports occur in Python, demonstrates the resulting ImportError with example modules, and provides three practical solutions—including importing modules directly, using lazy imports, and redesigning code structure—to prevent such issues.

Python Programming Learning Circle
Python Programming Learning Circle
Python Programming Learning Circle
How to Avoid Circular Imports in Python Code

When a Python program imports modules that mutually depend on each other, the interpreter raises an ImportError because the second module is only partially initialized. The article shows a real traceback from a Docker container where config.py imports crypto_xxx , which in turn imports config again, creating a circular import.

By examining the stack trace, we can see the import chain:

A module → B module

B module → A module

The following minimal example reproduces the problem:

<code># module_a
from module_b import fun_b

def fun_a():
    print('-> fun_a')
    fun_b()

def fun_c():
    print('-> fun_c')

if __name__ == '__main__':
    fun_a()
</code>
<code># module_b
from module_a import fun_c

def fun_b():
    print('-> fun_b')
    fun_c()
</code>

Running python3 module_a.py produces the same ImportError: cannot import name 'fun_b' from partially initialized module 'module_b' .

Solution 1: Import the module instead of the function

<code># module_a
import module_b

def fun_a():
    print('-> fun_a')
    module_b.fun_b()

if __name__ == '__main__':
    fun_a()
</code>

Solution 2: Use lazy (deferred) import inside the function

<code>def fun_a():
    print('-> fun_a')
    from module_b import fun_b
    fun_b()
</code>

Solution 3: Redesign the code structure to separate concerns, place shared utilities in a common module, and avoid mutual imports altogether.

In summary, circular imports arise from poorly planned module dependencies; fixing them involves either importing the whole module, deferring the import until runtime, or refactoring the code to eliminate the circular relationship.

backend@Importcode-structurecircular-import
Python Programming Learning Circle
Written by

Python Programming Learning Circle

A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.