Циклическая зависимость в 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?
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.
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.
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
●February 5, 2023
-
Botocore.Exceptions.NoCredentialsError: Unable to Locate Credentials
by Rahul Kumar Yadav●February 5, 2023
-
[Resolved] NameError: Name _mysql is Not Defined
by Rahul Kumar Yadav●February 5, 2023
-
Best Ways to Implement Regex New Line in Python
by Rahul Kumar Yadav●February 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
andAttributeError
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
- 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.
- 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
- Reproduce Circular Import Error in Python
- Solve Circular Import Error in Python
- Solve Circular Import Error Caused by Type Hint in Python
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
.
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.
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.
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.
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__
.
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.
- 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.
- 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.
- 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:
- Change Name of Working python script
- Import the module
- Avoid Circular Import
- Merge modules
- 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.