In python, it is possible to import one module or class from inside another. A circular dependency is created when one module is imported from another(directly or indirectly). Circular dependencies cause recursion, leading to infinite looping, failures, tight coupling, and many other problems. The function call keeps on repeating and creates an infinite loop.
When importing, python first checks the sys.modules folder to check if the module is already imported. Then it uses the module as it is. If the module is not present, then python first creates a new empty module which is in essence a dictionary. After that, it inserts the newly created module into the sys.modules folder and loads its code. Lastly, it executes the code in the new module’s workspace. Variables assigned to the module will have the value of the objects present in the module.
Ways to import modules
There are many ways in which we can import modules and classes in our programs. Some of them are:
- Import MODULE_NAME: This is the most common way to import a module in a program.
- from MODULE_NAME import * : imports everything from the required module and creates references in the current program to all public objects in the module(except the names starting with “__”). But since the module itself is not imported by itself, so module.name won’t work.
- Import MODULE_NAME as MN : The variable “MN” has been explicitly assigned the module and passed as a string.
- from MODULE_NAME import x,y,z : The x, y and z functions are called by reference from the module in the current workspace.
What causes circular dependencies?
The most common cause of circular dependency occurs when a python script is assigned the same name of some module in the sys.modules directory in python.
It might occur due to poor code structure and logical anomalies as well.
Unnecessary imports can also result in circular dependencies. For example, when you define a function(without using “__”) with the same name as the function inside an imported module, it might cause a wrong reference call leading to infinite looping of the python calls from inside the script.
When modules are interdependent on each other and causes cyclic dependency, python raises an error.
Example of a circular dependency
Lets look at a user defined block of code where cyclic dependency is done.
#example of circular import
print('In first function')
print('In second function')
print('In third function')
The output is:
In first function
In second function
In third function
Suggested : How to Check Version of Installed Python Modules
What does the error look like?
The error that is raised due to cyclic dependencies in python looks something like this:
ImportError: cannot import name '<name>' from partially initialized module '<module>' (most likely due to a circular import)...
How to fix circular dependency?
Circular dependencies are easy to fix. Here are the possible ways in which you can do that:
- Change the name of the python script: This is one of the most common fixes for this error. Make sure you name your working script something that won’t clash with the names of existing modules or classes. For example, don’t name your python script “numpy” when you know there already exists a module named numpy.
- Avoid unnecessary imports of modules: This can mostly happen with beginners. Avoid importing modules that you haven’t used in your code. With most IDEs nowadays, unused modules are highlighted hence they are easier to spot.
- Avoiding circular modules: As shown in the example above, avoid using circular imports in your code. When defining functions, make sure you don’t use cyclic dependencies.
- Merging possible modules: You can also try to merge user defined modules when possible to avoid this error.
In this article, we have looked at what circular dependencies are, what are their possible causes, the errors that they raise and also various ways in which we can fix them. Cyclic dependencies are very common in python and sometimes when you’re starting to learn a language, they can cause confusion. We hope you found the solution to your problem and if you want to know more, visit the official Python documentation.