Most likely due to a circular import python как исправить

Циклическая зависимость в Pytho возникает, когда два или более модуля зависят друг от друга. Это связано с тем, что каждый модуль определяется в терминах другого. Например: fu ctio A(): fu ctio B() fu ctio B(): fu ctio A() Приведенный выше код демонстрирует довольно очевидную циклическую зависимость. fu ctio A() вызывает fu ctio B(), следовательно, в зависимости от него, а fu [...]

Циклическая зависимость в Python возникает, когда два или более модуля зависят друг от друга. Это связано с тем, что каждый модуль определяется в терминах другого.

Например:

functionA():
    functionB()
functionB():
    functionA()

Приведенный выше код демонстрирует довольно очевидную циклическую зависимость. functionA() вызывает functionB(), следовательно, в зависимости от него, а functionB() вызывает functionA(). У этого типа циклической зависимости есть некоторые очевидные проблемы, которые мы опишем немного дальше в следующем разделе.

Циклическую зависимость

Проблемы с круговыми зависимостями

Циклические зависимости могут вызвать множество проблем в вашем коде. Например, это может привести к тесной связи между модулями и, как следствие, к снижению возможности повторного использования кода. Этот факт также усложняет сопровождение кода в долгосрочной перспективе.

Кроме того, циклические зависимости могут быть источником потенциальных сбоев, таких как бесконечные рекурсии, утечки памяти и каскадные эффекты. Если вы не будете осторожны и у вас есть циклическая зависимость в вашем коде, может быть очень сложно отладить множество потенциальных проблем, которые он вызывает.

Циклический импорт в Python – это форма циклической зависимости, которая создается с помощью оператора импорта в Python.

Например, давайте проанализируем следующий код:

# module1
import module2

def function1():
    module2.function2()

def function3():
    print('Goodbye, World!')
# module2
import module1

def function2():
    print('Hello, World!')
    module1.function3()
# __init__.py

import module1

module1.function1()

Когда Python импортирует модуль, он проверяет реестр модулей, чтобы убедиться, что он уже импортирован. Если модуль уже был зарегистрирован, Python использует этот существующий объект из кеша. Реестр модулей – это таблица модулей, которые были инициализированы и проиндексированы по имени модуля. К этой таблице можно получить доступ через sys.modules.

Если он не был зарегистрирован, Python находит модуль, при необходимости инициализирует его и выполняет в пространстве имен нового модуля.

В нашем примере, когда Python достигает import module2, он загружает и выполняет его. Однако module2 также вызывает module1, который, в свою очередь, определяет function1().

Проблема возникает, когда function2() пытается вызвать функцию module1 function3(). Поскольку модуль1 был загружен первым и, в свою очередь, загружен модуль2 до того, как он смог достичь function3(), эта функция еще не определена и выдает ошибку при вызове:

$ python __init__.py
Hello, World!
Traceback (most recent call last):
  File "__init__.py", line 3, in <module>
    module1.function1()
  File "/Users/scott/projects/sandbox/python/circular-dep-test/module1/__init__.py", line 5, in function1
    module2.function2()
  File "/Users/scott/projects/sandbox/python/circular-dep-test/module2/__init__.py", line 6, in function2
    module1.function3()
AttributeError: 'module' object has no attribute 'function3'

Как исправить?

Как правило, циклический импорт – это результат плохого дизайна. Более глубокий анализ программы мог бы сделать вывод, что зависимость на самом деле не требуется или что зависимые функции могут быть перемещены в другие модули, которые не будут содержать циклическую ссылку.

Простое решение состоит в том, что иногда оба модуля можно просто объединить в один более крупный. Результирующий код из нашего примера выше будет выглядеть примерно так:

# module 1  2

def function1():
    function2()

def function2():
    print('Hello, World!')
    function3()

def function3():
    print('Goodbye, World!')

function1()

Однако объединенный модуль может иметь некоторые несвязанные функции (тесная связь) и может стать очень большим, если в двух модулях уже есть много кода.

Так что, если это не сработает, можно было бы отложить импорт module2, чтобы импортировать его только тогда, когда это необходимо. Это можно сделать, поместив импорт module2 в определение function1():

# module 1

def function1():
    import module2
    module2.function2()

def function3():
    print('Goodbye, World!')

В этом случае Python сможет загрузить все функции в module1, а затем загрузить module2 только при необходимости.

Этот подход не противоречит синтаксису, поскольку в документации сказано: «Обычно, но не обязательно, помещать все операторы импорта в начало модуля».

В документации также говорится, что рекомендуется использовать import X вместо других операторов, таких как from module import * или from module import a, b, c.

Вы также можете увидеть много кодовых баз, использующих отложенный импорт, даже если нет циклической зависимости, которая ускоряет время запуска, поэтому это вообще не считается плохой практикой (хотя это может быть плохой дизайн, в зависимости от вашего проекта) .

Заключение

Циклический импорт – это особый случай циклических ссылок. Как правило, их можно решить с помощью улучшенного дизайна кода. Однако иногда результирующий дизайн может содержать большой объем кода или смешивать несвязанные функции (жесткая связь).

We love to use modules in Python and why not, they provide additional functionalities, better coding practice, and always create a proper structure while using. But many times unknowingly, we can run into python circular import problems if we accidentally have another file named as module’s name. As python prefers importing from the local current directory first and then from site-packages, it will create a circular import problem.

Generally, the Python Circular Import problem occurs when you accidentally name your working file the same as the module name and those modules depend on each other. This way the python opens the same file which causes a circular loop and eventually throws an error.

For example, when you name your file as random.py and try to import “from random import randint”, it’ll throw a circular import error (also termed as from partially initialized module).

In this post, we’ll have a look at all the causes and their solutions for circular import.

How Circular Import Is Identified?

Python Circular Import Flowchart

Then a module calls an object within itself, circular import error is raised. Let’s consider an example where you are working on a ‘rea.py’ python file and you write a code as ‘from rea import x’. This will cause python to import the object x from the rea module.

This will cause a circular call within the code and it’ll throw an exception with an error mentioned as “ImportError: cannot import name ‘x’ from partially initialized module ‘rea’ (most likely due to a circular import) (/home/pythonpool/rea.py)”.

This exception is raised when you try to import any type of object. There are no exceptions.

Tip: Circular import is only raised when you import object from module. It is not raised when you try to import module itself. So, in above example, “import rea” will work just fine.

“Other Commands Don’t Work After on_message” in Discord Bots

How to fix Python Circular Import?

There are several workarounds to solve the circular import problem. Each of these workarounds has its different use cases. Make sure you use the solution that suits best for your problem.

Conditional Import is also one of the ways by which you can handle such cases but does not try to use try-except blocks to fix circular imports as the core problem of importing variables still remain even if we ignore it.

Importing The Module Itself

There is a good workaround Python circular import error that you can import the module itself rather than importing object/function from the module. This way you can import and use all the objects and variables from the module.

Suppose, a module named module_name has function func_name, and you want to import it but it throws a circular error.

The easiest way to make this work is by importing the module_name itself. The following example will help you to understand it –

rea.py –

import rea

x=1

if __name__ == '__main__':
    print(rea.x)

Even if you are calling the same module, it’ll work. Use these cases to fix the issues in flask and Django where the filenames can match the pre-defined module names.

Rename Your Working file

Sometimes, we can name our working file to module name without knowing its consequences (Even I did it many times :P). Renaming the file will work perfectly in such cases. For example, if you want to use the numpy module, you should avoid your working file naming numpy.py.

Here’s an example –

– numpy.py –

from numpy import array

x = array([1, 2, 3])
ImportError: cannot import name 'array' from partially initialized module 'numpy' (most likely due to a circular import) (/home/pythonpool/numpy.py)

Now, rename our working file to a different name –

– pool_numpy.py –

from numpy import array

x = array([1, 2, 3])
print(x)
[1 2 3]

Just as we avoid naming variables to built-in variables to avoid issues, you need to avoid naming your file to module name to avoid conflicts.

Botocore.Exceptions.NoCredentialsError: Unable to Locate Credentials

Avoid Circular Import Calls

Consider the following example –

– module1.py –

from module2 import func2

def func1():
	func2()

– module2.py –

from module1 import func1

def func2():
	func1()

Command to run –

python .module1.py
Traceback (most recent call last):
  File "/home/pythonpool/module1.py", line 1, in <module>
    from module2 import func2
  File "/home/pythonpool/module2.py", line 1, in <module>
    from module1 import func1
  File "/home/pythonpool/module1.py", line 1, in <module>
    from module2 import func2
ImportError: cannot import name 'func2' from partially initialized module 'module2' (most likely due to a circular import) (/home/pythonpool/module2.py)

The above example demonstrates a situation where you try to import a variable from module2 which is partially initialized (python doesn’t know that func2 even exists or not).

In such cases try to copy the required function/object to your working file.

In the above example, if you declare func2 itself in module1, it’ll not be of any problem.

Solve Circular Import Error In Django

Ever tried importing Django modules/classes in your Django project? You’ll definitely encounter a python circular import error once in such scenarios. If you try to implement the Django model manually by directly importing it, it’ll throw an error.

For example, you have your Django installed apps as follows –


INSTALLED_APPS = (
    'app1',
)

And you want to use the structure of app1, you might import it directly in your python file considering its installed app. Something like this –

from app1.models import App1

Then most likely, you’ll encounter the python circular import error in your code. This is the incorrect way of importing a Model in your Django Application. Following is the correct way to do it –

For Django <=1.7:

from django.db.models import get_model
MyModel = get_model('app1',  'App1')

For Django > 1.7:

from django.apps import apps
apps.get_model('app1.App1')

This way the model ‘App1’ from app ‘app1’ will be imported into your Django application directly.

Solution for Python Circular Import Error In Flask

Similar to Django, flask also has circular import issues especially when you’re dealing with SQLAlchemy. If you try to use the database model of SQLAlchemy (declared in the main app file) in a different file, it’ll throw a circular import error.

Consider the following examples –

– app.py –

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__ name __)
db = SQLAlchemy(app)  
from models import routes

– routes.py –

This is indeed a circular import as app.py called routes and routes call DB from app.py. To fix such issues we create a separate extension for a database where we initialize the SQLAlchemy database.

from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()

This can be imported in app.py and models.py and used accordingly.

FAQs

Is there any python circular import detector?

Pycycle is a Github project which aims to detect circular import problems in your code. This tool has good command-line usage with multiple arguments usage.

Importing Static Variable at class level cause circular import?

Yes, if there is another import statement calling working module again, then it may cause circular import.

What causes circular import problems in __init__.py file?

__init__ file is responsible for importing and initializing packages. During this process, we always tend to import other modules from the package. So, if your other module calls back to another module that is yet to initialize in __init__, it’ll throw a circular import.

References

Python Import System: How searching of Modules works in Python.


Trending Python Articles

  • “Other Commands Don’t Work After on_message” in Discord Bots

    “Other Commands Don’t Work After on_message” in Discord Bots

    February 5, 2023

  • Botocore.Exceptions.NoCredentialsError: Unable to Locate Credentials

    Botocore.Exceptions.NoCredentialsError: Unable to Locate Credentials

    by Rahul Kumar YadavFebruary 5, 2023

  • [Resolved] NameError: Name _mysql is Not Defined

    [Resolved] NameError: Name _mysql is Not Defined

    by Rahul Kumar YadavFebruary 5, 2023

  • Best Ways to Implement Regex New Line in Python

    Best Ways to Implement Regex New Line in Python

    by Rahul Kumar YadavFebruary 5, 2023

Consider the following example python package where a.py and b.py depend on each other:

/package
    __init__.py
    a.py
    b.py

Types of circular import problems

Circular import dependencies typically fall into two categories depending
on what you’re trying to import and where you’re using it inside each
module. (And whether you’re using python 2 or 3).

1. Errors importing modules with circular imports

In some cases, just importing a module with a circular import dependency
can result in errors even if you’re not referencing anything from the
imported module.

There are several standard ways to import a module in python

import package.a           # (1) Absolute import
import package.a as a_mod  # (2) Absolute import bound to different name
from package import a      # (3) Alternate absolute import
import a                   # (4) Implicit relative import (deprecated, python 2 only)
from . import a            # (5) Explicit relative import

Unfortunately, only the 1st and 4th options actually work when you
have circular dependencies (the rest all raise ImportError
or AttributeError). In general, you shouldn’t be using the
4th syntax, since it only works in python2 and runs the risk of
clashing with other 3rd party modules. So really, only the first
syntax is guaranteed to work.

EDIT: The ImportError and AttributeError issues only occur in
python 2. In python 3 the import machinery has been rewritten and all
of these import statements (with the exception of 4) will work, even with
circular dependencies. While the solutions in this section may help refactoring python 3 code, they are mainly intended
for people using python 2.

Absolute Import

Just use the first import syntax above. The downside to this method is
that the import names can get super long for large packages.

In a.py

import package.b

In b.py

import package.a

Defer import until later

I’ve seen this method used in lots of packages, but it still feels
hacky to me, and I dislike that I can’t look at the top of a module
and see all its dependencies, I have to go searching through all the
functions as well.

In a.py

def func():
    from package import b

In b.py

def func():
    from package import a

Put all imports in a central module

This also works, but has the same problem as the first method, where
all the package and submodule calls get super long. It also has two
major flaws — it forces all the submodules to be imported, even if
you’re only using one or two, and you still can’t look at any of the
submodules and quickly see their dependencies at the top, you have to
go sifting through functions.

In __init__.py

from . import a
from . import b

In a.py

import package

def func():
    package.b.some_object()

In b.py

import package

def func():
    package.a.some_object()

2. Errors using imported objects with circular dependencies

Now, while you may be able to import a module with a circular import
dependency, you won’t be able to import any objects defined in the module
or actually be able to reference that imported module anywhere
in the top level of the module where you’re importing it. You can,
however, use the imported module inside functions and code blocks that don’t
get run on import.

For example, this will work:

package/a.py

import package.b

def func_a():
    return "a"

package/b.py

import package.a

def func_b():
    # Notice how package.a is only referenced *inside* a function
    # and not the top level of the module.
    return package.a.func_a() + "b"

But this won’t work

package/a.py

import package.b

class A(object):
    pass

package/b.py

import package.a

# package.a is referenced at the top level of the module
class B(package.a.A):
    pass

You’ll get an exception

AttributeError: module ‘package’ has no attribute ‘a’

Generally, in most valid cases of circular dependencies, it’s possible
to refactor or reorganize the code to prevent these errors and move
module references inside a code block.

Today We are Going To Solve ImportError: cannot import name ‘…’ from partially initialized module ‘…’ (most likely due to a circular import) in Python. Here we will Discuss All Possible Solutions and How this error Occurs So let’s get started with this Article.

Contents

  • 1 How to Fix ImportError: cannot import name ‘…’ from partially initialized module ‘…’ (most likely due to a circular import) Error?
    • 1.1 Solution 1 : Change the file name
    • 1.2 Solution 2 : Remove imports
  • 2 Conclusion
    • 2.1 Also Read This Solutions
  1. How to Fix ImportError: cannot import name ‘…’ from partially initialized module ‘…’ (most likely due to a circular import) Error?

    To Fix ImportError: cannot import name ‘…’ from partially initialized module ‘…’ (most likely due to a circular import) Error just Change the file name. Just change the file name in which you are working on. This will simply solve your error. Try this.

  2. ImportError: cannot import name ‘…’ from partially initialized module ‘…’ (most likely due to a circular import)

    To Fix ImportError: cannot import name ‘…’ from partially initialized module ‘…’ (most likely due to a circular import) Error just Remove imports. The reason of occurring the error is circular import. So just remove the import and it will solve your error. You have to remove any of the imports which are given below. So it will work easily.
    from core.excute import main from pxxtf import * Remove one of the imports listed above and it should work.

Solution 1 : Change the file name

Just change the file name in which you are working on. This will simply solve your error. Try this.

Solution 2 : Remove imports

The reason of occurring the error is circular import. So just remove the import and it will solve your error. You have to remove any of the imports which are given below. So it will work easily.

from core.excute import main
from pxxtf import *

Remove one of the imports listed above and it should work.

Conclusion

So these were all possible solutions to this error. I hope your error has been solved by this article. In the comments, tell us which solution worked? If you liked our article, please share it on your social media and comment on your suggestions. Thank you.

Also Read This Solutions

  • FileNotFoundError: [Errno 2] No such file or directory
  • ESLint Parsing error: Unexpected token
  • npm ERR! code E401 npm ERR! Incorrect or missing password
  • Error: [PrivateRoute] is not a component. All component children of must be a or
  • Attribute: ‘str’ object has no attribute

  1. Reproduce Circular Import Error in Python
  2. Solve Circular Import Error in Python
  3. Solve Circular Import Error Caused by Type Hint in Python

Python Circular Import

In this article, we will learn how circular imports commonly arise and the main ways to fix them. We will also see how to fix a circular import error caused by a type hint in python.

Reproduce Circular Import Error in Python

Have you ever come across an error when trying to import a module? In this case, we get an error that is shown below.

from My_Module_A import My_FUNC_A

def My_main_Func():
    My_FUNC_A()

if __name__=='main':
    My_main_Func()

Output:

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

It tells us that the most likely cause is a circular import. Here is the simplest and most common way that this kind of import cycle can happen at runtime main tried to import something from My_Module_A.

python circular import - example one

So, it starts initializing My_Module_A and running the code from My_Module_A, but the first line in My_Module_A is to import something from module MY_Module_B.

So, it stops initializing module My_Module_A because MY_Module_B has to be initialized first. And then, it hops over to MY_Module_B and starts running that code instead.

But, the first line in module MY_Module_B is needed something from My_Module_A, so it stops running MY_Module_B and goes over to My_Module_A.

And it would like to start initializing My_Module_A, but it realizes that My_Module_A is already in the initialization process. So that’s where the error occurs.

We can see this chain of events unfold in the traceback. Here we see in main.py; it tries to import function My_FUNC_A from module My_Module_A, which triggered the import of function MY_Func_B2 from module MY_Module_B.

And, MY_Module_B.py triggered the import of function My_FUNC_A again from module My_Module_A, where the final error occurred.

Traceback (most recent call last):
  File "c:UsersDellDesktopdemomain.py", line 1, in <module>
    from My_Module_A import My_FUNC_A
  File "c:UsersDellDesktopdemoMy_Module_A.py", line 1, in <module>
    from MY_Module_B, import MY_Func_B2
  File "c:UsersDellDesktopdemoMY_Module_B.py", line 1, in <module>
    from My_Module_A import My_FUNC_A
ImportError: cannot import name 'My_FUNC_A' from partially initialized module 'My_Module_A' (most likely due to a circular import) (c:UsersDellDesktopdemoMy_Module_A.py)

We have an import time cycle between the modules My_Module_A and MY_Module_B, but if you look at the names we imported, we do not use them at import time.

We use them when this function My_FUNC_A() or when this function MY_Func_B2() is called. Since we are not calling these functions at import time, there is no true cyclic dependency, which means we can eliminate this import cycle.

Solve Circular Import Error in Python

There are three common ways to resolve this issue; the first is to take your import and put it inside the function.

In python, imports can happen at any time, including when a function is called; if you need this function MY_Func_B1(), then it could be the import inside the My_FUNC_A() function.

def My_FUNC_A():
    from MY_Module_B import MY_Func_B1
    MY_Func_B1()

It could be even more efficient because if you never call the function My_FUNC_A(), then it may be that you never even have to import MY_Func_B1 at all. For example, let’s say you have a bunch of different functions in My_Module_A, and many different ones use this function MY_Func_B1().

In that case, the better solution would be to import the module MY_Module_B directly and in the functions where you use it, use the longer name like MY_Module_B.MY_Func_B1(). So go ahead and do this conversion for all modules involved in the cycle.

import MY_Module_B

def My_FUNC_A():
   MY_Module_B.MY_Func_B1()

Let’s see how this resolves the import cycle at runtime error. First, our My_main_Func() function tries to import something from My_Module_A, causing My_Module_A to start running. Then, in My_Module_A.py, we get to import module MY_Module_B, which triggers MY_Module_B to start running.

In MY_Module_B.py, when we get to the import module My_Module_A, the module has already started initializing; this module object technically exists. Since it exists, it does not begin rerunning this.

It just says, okay, that exists, so the MY_Module_B module will continue, finish its import, and then after that import is done, the My_Module_A module will finish importing.

python circular import - example two

Output:

The third and final common way to eliminate this import cycle is to merge the two modules. So, again, no imports, no import cycles; however, if you had two or maybe even more modules in the first place, you probably had them for a reason.

We are not just going to recommend that you take all of your modules and merge them into one; that would be silly. So, you should probably prefer using one of the first two methods.

Source code of My_Module_A.py file.

import MY_Module_B

def My_FUNC_A():
   print(MY_Module_B.MY_Func_B1())

Source code of MY_Module_B.py file.

import My_Module_A

def MY_Func_B1():
    return 5 + 10

def MY_Func_B2():
    My_Module_A.My_FUNC_A()

Source code of main.py file.

from My_Module_A import My_FUNC_A

def My_main_Func():
    My_FUNC_A()

if __name__=='main':
    My_main_Func()

Solve Circular Import Error Caused by Type Hint in Python

Let’s look at another example, the following most common kind of import cycle you will run due to using type hints. This example is unlike the previous one because type annotations are defined on a function or class definition.

When the function is defined, or the class is defined but not defined when we run it, the most common use case of type hinting is not even at runtime. If all we care about is static analysis, then we do not even need to do the import at runtime.

The typing module provides this variable, TYPE_CHECKING is a false constant at runtime. So, if we put all the imports we need for type checking in one of these, then none will happen at runtime.

Avoiding the import loop altogether, if you import this class Mod_A_class, you will get a name error because this name Mod_A_class has not been imported.

python circular import - example three

Output:

Traceback (most recent call last):
  File "c:UsersDellDesktopdemomain.py", line 1, in <module>
    from My_Module_A import My_FUNC_A
  File "c:UsersDellDesktopdemoMy_Module_A.py", line 9, in <module>
    from MY_Module_B, import MY_Func_B1
  File "c:UsersDellDesktopdemoMY_Module_B.py", line 22, in <module>
    class Mod_b_class:
  File "c:UsersDellDesktopdemoMY_Module_B.py", line 23, in Mod_b_class
    def __init__(self,a : Mod_A_class):
NameError: name 'Mod_A_class' is not defined

To fix this, add this from __future__ import annotations. What does this?

It changes the way annotations work; instead of evaluating Mod_b_class as a name, all annotations are converted to strings.

python circular import - example four

So now you do not get an error at runtime here because even though the name Mod_b_class is not imported, the string Mod_b_class certainly exists. However, you should be aware that whenever you do one of these from __future__ imports, it is not necessarily guaranteed behavior forever.

Now, this causes your annotations to be handled as strings, but there is a competing proposal to make them just be evaluated lazily. Hence, they are not evaluated unless you try to look at them and inspect your type hints at runtime.

This probably will not make any difference for your code base, but you should still be aware. An alternative solution is to again use import modules instead of from module imports, and you will still need the annotations from __future__.

python circular import - example five

Complete source code of module My_Module_A.py.

# from __future__ import annotations

# from typing import TYPE_CHECKING

# from MY_Module_B import MY_Func_B1

# if TYPE_CHECKING:
#     from MY_Module_B import Mod_b_class

# def My_FUNC_A():
#     b : Mod_b_class = MY_Func_B1()


# class Mod_A_class:
#     def __init__(self,b : Mod_b_class):
#         self.b=b


from __future__ import annotations
import MY_Module_B 

def My_FUNC_A():
    b : MY_Module_B.Mod_b_class = MY_Module_B.MY_Func_B1()

class Mod_A_class:
    def __init__(self,b : MY_Module_B.Mod_b_class):
        self.b=b

Complete source code of module MY_Module_B.py.

from __future__ import annotations

import My_Module_A

def MY_Func_B1():
    ...

class Mod_b_class:
    def __init__(self,a : My_Module_A.Mod_A_class):
        self.a =a

Complete source code of main.py file.

from My_Module_A import My_FUNC_A

def My_main_Func():
    My_FUNC_A()

if __name__=='main':
    My_main_Func()

In python, a module can be made by importing other modules. In some cases, a Circular dependency is created. Circular dependency is the case when some modules depend on each other. It can create problems in the script such as tight coupling, and potential failure.

To run the script without any error the Circular dependency has to be removed. Circular dependency can be created in many ways. With a well-designed program, these cases can be avoided.

Python Circular Imports:

Circular importing is a conceptual error that is formed due to circular dependency created with the import statement in our Python program.

  1. Python Circular Imports is a type of Circular dependency. It occurs in python when two or more models import each other and it repeats the importing connection into an infinite circular call.
  2. With Circular Imports, the python script gives an error. To run the python script it has to be removed and it is very difficult to find and remove the script manually.
  3. Circular imports are created because of the bad coding design and implementation-related logical anomalies.

Here is a situation shown using three separate programs:

# module1 created
import module2
def function1():
    module2.function2()
def function3():
    print('Hasta la vista, Gaurav!')

# module 2
import module1
def function2():
    print('Hey, Gaurav')
    module1.function3()

# __init.py
import module1
module1.function1()

Explanation:

Here, we have defined three programs. 2 of them are treated as modules. In the first code function1()  has been called that has a module2.function2() within itself as the calling function. The function2() of module 2 again has a print() and function3 and the body of function3() has some print().

Finally, the __init__.py is calling module1.function1(). This circular calls of importing statements and their associated function will create an error.

NOTE:

When Python performs the importing of a module, it verifies and goes through the module registry to identify if the module was already imported. In case the module has already been there registered, Python uses its existing object from cache.

The module registry is nothing but a data structure or tabular structure containing information about multiple imports (predefined and user defined) of modules that were initialized and indexed with module name(s). Developers can access this table using sys.modules.

Fixing Circular Imports in python

There are many ways by which Circular imports can be avoided. Some of them are:

  1. Change Name of Working python script
  2. Import the module
  3. Avoid Circular Import
  4. Merge modules
  5. Import when need

Change Name of working python script:

Changing the name of the Working file different from the module which is imported in the script can avoid the Circular Imports problem.

Import the module:

Avoid importing objects or functions from a module that can cause Circular Imports. It is good to import the whole module to avoid the Circular Import.

Avoid Circular Import:

There are many cases where one module function depends on another model which in turn depends on it. This case mostly creates Circular Imports.

Merge modules:

When one module depends on another model and that module depends on first then it is good practice to Merge both the modules to avoid Circular Imports.

Program:

# one module
def fun1():
     print('In function 1')
    fun2()
def fun2():
    print('In function2')
    function3()
def function3():
    print('In function 3')
fun1()

Explanation:

Here, merge both module1 and module2, so that the user-defined functions within them come under one module.

Import when need:

The python module can be imported anywhere in the program. It is not necessary for python to first import the module and start working over it. Importing the module before one line where it is needed to avoid Circular Import.

Program:

def fun1():
    print('In function 1')
    import newmodule
    newmodule.fun3()
def fun2():
    print('In function 2')

Explanation:

Here, In function one imports the newmodule before calling the fun3.

Conclusion:

We hope this article has given a crisp idea on how to stay ahead of circular import issue. We learn about Circular dependency, Circular Imports, and various ways to solve the problem of Circular imports. Circular Imports reduce code reusability and create infinite recursions leading to inefficient programming and memory leaks, and can even lead to cascade effects. It is good programming practice to avoid Circular Imports.

Понравилась статья? Поделить с друзьями:
  • Mount and blade warband как изменить характеристики персонажа
  • Mosquito error address already in use
  • Mount and blade warband как изменить характеристики оружия
  • Moscow wifi free ошибка 100
  • Mount and blade warband как изменить флаг