国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Home Backend Development Python Tutorial Different Ways to Fix Circular Imports in Python

Different Ways to Fix Circular Imports in Python

Nov 05, 2024 am 02:21 AM

Have you ever come across circular imports in Python? Well, it’s a very common code smell that indicates something’s wrong with the design or structure.

Circular Import Example

How does circular import occur? This import error usually occurs when two or more modules depending on each other try to import before fully initializing.

Let’s say we have two modules: module_1.py and module_2.py.

# module_1.py
from module_2 import ModY
class ModX:
    mody_obj = ModY()
# module_2.py
from module_1 import ModX
class ModY:
    modx_obj = ModX()

In the above code snippets, both module_1 and module_2 are mutually dependent on each other.

The initialization of mody_obj in module_1 depends on module_2 and the initialization of modx_obj in module_2 depends on module_1.

This is what we call a circular dependency. Both modules will stuck in the import loops while attempting to load each other.

If we run module_1.py, we’ll get the following traceback.

Traceback (most recent call last):
  File "module_1.py", line 1, in <module>
    from module_2 import ModY
  File "module_2.py", line 1, in <module>
    from module_1 import ModX
  File "module_1.py", line 1, in <module>
    from module_2 import ModY
ImportError: cannot import name 'ModY' from partially initialized module 'module_2' (most likely due to a circular import)

This error explains the situation of circular import. When the program attempted to import ModY from module_2, at that time module_2 wasn’t fully initialized (due to another import statement that attempts to import ModX from module_1).

How to fix circular imports in Python? There are different ways to get rid of circular imports in Python.

Fix Circular Imports in Python

Move code into a common file

We can move the code into a common file to avoid import errors and then try to import the modules from that file.

# main.py ----> common file
class ModX:
    pass

class ModY:
    pass

In the above code snippet, we moved the classes ModX and ModY into a common file (main.py).

# module_1.py
from main import ModY

class Mod_X:
    mody_obj = ModY()
# module_2.py
from main import ModX

class Mod_Y:
    modx_obj = ModX()

Now, module_1 and module_2 import the classes from main which fixes the circular import situation.

There is a problem with this approach, sometimes the codebase is so large that it becomes risky to move the code into another file.

Move the import to the end of the module

We can shift the import statement at the end of the module. This will give time to fully initialize the module before importing another module.

# module_1.py
class ModX:
   pass

from module_2 import ModY

class Mod_X:
   mody_obj = ModY()
# module_2.py
class ModY:
   pass

from module_1 import ModX

Importing module within the class/function scope

Importing modules within the class or function scope can avoid circular imports. This allows the module to be imported only when the class or function is invoked. It’s relevant when we want to minimize memory use.

# module_1.py
class ModX:
  pass

class Mod_X:
   from module_2 import ModY
   mody_obj = ModY()
# module_2.py
class ModY:
   pass

class Mod_Y:
   from module_1 import ModX
   modx_obj = ModX()

We moved the import statements within classes Mod_X and Mod_Y scope in module_1 and module_2 respectively.

If we run either module_1 or module_2, we’ll not get a circular import error. But, this approach makes the class accessible only within the class’s scope, so we can’t leverage the import globally.

Using module name/alias

Using the module name or just an alias like this solves the problem. This allows both modules to load fully by deferring circular dependency until runtime.

# module_1.py
from module_2 import ModY
class ModX:
    mody_obj = ModY()
# module_2.py
from module_1 import ModX
class ModY:
    modx_obj = ModX()

Using importlib library

We can also use the importlib library to import the modules dynamically.

Traceback (most recent call last):
  File "module_1.py", line 1, in <module>
    from module_2 import ModY
  File "module_2.py", line 1, in <module>
    from module_1 import ModX
  File "module_1.py", line 1, in <module>
    from module_2 import ModY
ImportError: cannot import name 'ModY' from partially initialized module 'module_2' (most likely due to a circular import)
# main.py ----> common file
class ModX:
    pass

class ModY:
    pass

Circular Imports in Python Packages

Usually, circular imports come from modules within the same package. In complex projects, the directory structure is also complex, with packages within packages.

These packages and sub-packages contain __init__.py files to provide easier access to modules. That’s where sometimes arises circular dependencies among modules unintentionally.

We have the following directory structure.

# module_1.py
from main import ModY

class Mod_X:
    mody_obj = ModY()

We have a package mainpkg and a main.py file. We have two sub-packages modpkg_x and modpkg_y within mainpkg.

Here’s what each Python file within modpkg_x and modpkg_y looks like.

mainpkg/modpkg_x/__init__.py

# module_2.py
from main import ModX

class Mod_Y:
    modx_obj = ModX()

This file imports both classes (ModX and ModA) from module_1 and module_1_1.

mainpkg/modpkg_x/module_1.py

# module_1.py
class ModX:
   pass

from module_2 import ModY

class Mod_X:
   mody_obj = ModY()

The module_1 imports a class ModY from module_2.

mainpkg/modpkg_x/module_1_1.py

# module_2.py
class ModY:
   pass

from module_1 import ModX

The module_1_1 imports nothing. It is not dependent on any module.

mainpkg/modpkg_y/__init__.py

# module_1.py
class ModX:
  pass

class Mod_X:
   from module_2 import ModY
   mody_obj = ModY()

This file imports the class ModY from module_2.

mainpkg/modpkg_y/module_2.py

# module_2.py
class ModY:
   pass

class Mod_Y:
   from module_1 import ModX
   modx_obj = ModX()

The module_2 imports a class ModA from the module_1_1.

We have the following code within the main.py file.

root_dir/main.py

# module_1.py
import module_2 as m2

class ModX:
    def __init__(self):
        self.mody_obj = m2.ModY()

The main file imports a class ModY from module_2. This file is dependent on module_2.

If we visualize the import cycle here, it would look like the following ignoring the __init__.py files within the modpkg_x and modpkg_y.

Different Ways to Fix Circular Imports in Python

We can see that the main file depends on module_2, module_1 also depends on module_2 and module_2 depends on module_1_1. There is no import cycle.

But you know, modules depend on their __init__.py file, so the __init__.py file initializes first, and modules are re-imported.

Different Ways to Fix Circular Imports in Python

This is what the import cycle looks like now.

Different Ways to Fix Circular Imports in Python

This made module_1_1 depend on module_1, which is a fake dependency.

If this is the case, empty the sub-packages __init__.py files and using a separate __init__.py file can help by centralizing imports at the package level.

# module_1.py
from module_2 import ModY
class ModX:
    mody_obj = ModY()

In this structure, we added another sub-package subpkg within mainpkg.

mainpkg/subpkg/__init__.py

# module_2.py
from module_1 import ModX
class ModY:
    modx_obj = ModX()

This will allow internal modules to import from a single source, reducing the need for cross-imports.

Now we can update the import statement within the main.py file.

root_dir/main.py

Traceback (most recent call last):
  File "module_1.py", line 1, in <module>
    from module_2 import ModY
  File "module_2.py", line 1, in <module>
    from module_1 import ModX
  File "module_1.py", line 1, in <module>
    from module_2 import ModY
ImportError: cannot import name 'ModY' from partially initialized module 'module_2' (most likely due to a circular import)

This solves the problem of circular dependency between the modules within the same package.

Conclusion

Circular dependency or import in Python is a code smell which is an indication of serious re-structuring and refactoring of the code.

You can try any of these above-mentioned ways to avoid circular dependency in Python.


?Other articles you might be interested in if you liked this one

?Template Inheritance in Flask with Example.

?Difference between exec() and eval() with Examples.

?Understanding the Use of global Keyword in Python.

?Python Type Hints: Functions, Return Values, Variable.

?Why Slash and Asterisk Used in Function Definition.

?How does the learning rate affect the ML and DL models?


That’s all for now.

Keep Coding??.

The above is the detailed content of Different Ways to Fix Circular Imports in Python. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

PHP Tutorial
1502
276
How to handle API authentication in Python How to handle API authentication in Python Jul 13, 2025 am 02:22 AM

The key to dealing with API authentication is to understand and use the authentication method correctly. 1. APIKey is the simplest authentication method, usually placed in the request header or URL parameters; 2. BasicAuth uses username and password for Base64 encoding transmission, which is suitable for internal systems; 3. OAuth2 needs to obtain the token first through client_id and client_secret, and then bring the BearerToken in the request header; 4. In order to deal with the token expiration, the token management class can be encapsulated and automatically refreshed the token; in short, selecting the appropriate method according to the document and safely storing the key information is the key.

How to iterate over two lists at once Python How to iterate over two lists at once Python Jul 09, 2025 am 01:13 AM

A common method to traverse two lists simultaneously in Python is to use the zip() function, which will pair multiple lists in order and be the shortest; if the list length is inconsistent, you can use itertools.zip_longest() to be the longest and fill in the missing values; combined with enumerate(), you can get the index at the same time. 1.zip() is concise and practical, suitable for paired data iteration; 2.zip_longest() can fill in the default value when dealing with inconsistent lengths; 3.enumerate(zip()) can obtain indexes during traversal, meeting the needs of a variety of complex scenarios.

What are python iterators? What are python iterators? Jul 08, 2025 am 02:56 AM

InPython,iteratorsareobjectsthatallowloopingthroughcollectionsbyimplementing__iter__()and__next__().1)Iteratorsworkviatheiteratorprotocol,using__iter__()toreturntheiteratorand__next__()toretrievethenextitemuntilStopIterationisraised.2)Aniterable(like

Python FastAPI tutorial Python FastAPI tutorial Jul 12, 2025 am 02:42 AM

To create modern and efficient APIs using Python, FastAPI is recommended; it is based on standard Python type prompts and can automatically generate documents, with excellent performance. After installing FastAPI and ASGI server uvicorn, you can write interface code. By defining routes, writing processing functions, and returning data, APIs can be quickly built. FastAPI supports a variety of HTTP methods and provides automatically generated SwaggerUI and ReDoc documentation systems. URL parameters can be captured through path definition, while query parameters can be implemented by setting default values ??for function parameters. The rational use of Pydantic models can help improve development efficiency and accuracy.

How to test an API with Python How to test an API with Python Jul 12, 2025 am 02:47 AM

To test the API, you need to use Python's Requests library. The steps are to install the library, send requests, verify responses, set timeouts and retry. First, install the library through pipinstallrequests; then use requests.get() or requests.post() and other methods to send GET or POST requests; then check response.status_code and response.json() to ensure that the return result is in compliance with expectations; finally, add timeout parameters to set the timeout time, and combine the retrying library to achieve automatic retry to enhance stability.

Python variable scope in functions Python variable scope in functions Jul 12, 2025 am 02:49 AM

In Python, variables defined inside a function are local variables and are only valid within the function; externally defined are global variables that can be read anywhere. 1. Local variables are destroyed as the function is executed; 2. The function can access global variables but cannot be modified directly, so the global keyword is required; 3. If you want to modify outer function variables in nested functions, you need to use the nonlocal keyword; 4. Variables with the same name do not affect each other in different scopes; 5. Global must be declared when modifying global variables, otherwise UnboundLocalError error will be raised. Understanding these rules helps avoid bugs and write more reliable functions.

How to parse an HTML table with Python and Pandas How to parse an HTML table with Python and Pandas Jul 10, 2025 pm 01:39 PM

Yes, you can parse HTML tables using Python and Pandas. First, use the pandas.read_html() function to extract the table, which can parse HTML elements in a web page or string into a DataFrame list; then, if the table has no clear column title, it can be fixed by specifying the header parameters or manually setting the .columns attribute; for complex pages, you can combine the requests library to obtain HTML content or use BeautifulSoup to locate specific tables; pay attention to common pitfalls such as JavaScript rendering, encoding problems, and multi-table recognition.

Access nested JSON object in Python Access nested JSON object in Python Jul 11, 2025 am 02:36 AM

The way to access nested JSON objects in Python is to first clarify the structure and then index layer by layer. First, confirm the hierarchical relationship of JSON, such as a dictionary nested dictionary or list; then use dictionary keys and list index to access layer by layer, such as data "details"["zip"] to obtain zip encoding, data "details"[0] to obtain the first hobby; to avoid KeyError and IndexError, the default value can be set by the .get() method, or the encapsulation function safe_get can be used to achieve secure access; for complex structures, recursively search or use third-party libraries such as jmespath to handle.

See all articles