ImportError: cannot import name '…' from partially initialized module '…' (most likely due to a circular import)
Question:
I’m upgrading an application from Django 1.11.25 (Python 2.6) to Django 3.1.3 (Python 3.8.5) and, when I run manage.py makemigrations
, I receive this message:
File "/home/eduardo/projdevs/upgrade-intra/corporate/models/section.py", line 9, in <module>
from authentication.models import get_sentinel**
ImportError: cannot import name 'get_sentinel' from partially initialized module 'authentication.models' (most likely due to a circular import) (/home/eduardo/projdevs/upgrade-intra/authentication/models.py)**
My models are:
authentication / models.py
from django.conf import settings
from django.contrib.auth.models import AbstractUser, UserManager
from django.db import models
from django.db.models.signals import post_save
from django.utils import timezone
from corporate.constants import GROUP_SUPPORT
from corporate.models import Phone, Room, Section
from library.exceptions import ErrorMessage
from library.model import update_through_dict
from .constants import INTERNAL_USER, EXTERNAL_USER, SENTINEL_USERNAME, SPECIAL_USER, USER_TYPES_DICT
class UserProfile(models.Model):
user = models.OneToOneField(
'User',
on_delete=models.CASCADE,
unique=True,
db_index=True
)
...
phone = models.ForeignKey('corporate.Phone', on_delete=models.SET_NULL, ...)
room = models.ForeignKey('corporate.Room', on_delete=models.SET_NULL, ...)
section = models.ForeignKey('corporate.Section', on_delete=models.SET_NULL, ...)
objects = models.Manager()
...
class CustomUserManager(UserManager):
def __init__(self, type=None):
super(CustomUserManager, self).__init__()
self.type = type
def get_queryset(self):
qs = super(CustomUserManager, self).get_queryset()
if self.type:
qs = qs.filter(type=self.type).order_by('first_name', 'last_name')
return qs
def get_this_types(self, types):
qs = super(CustomUserManager, self).get_queryset()
qs = qs.filter(type__in=types).order_by('first_name', 'last_name')
return qs
def get_all_excluding(self, types):
qs = super(CustomUserManager, self).get_queryset()
qs = qs.filter(~models.Q(type__in=types)).order_by('first_name', 'last_name')
return qs
class User(AbstractUser):
type = models.PositiveIntegerField('...', default=SPECIAL_USER)
username = models.CharField('...', max_length=256, unique=True)
first_name = models.CharField('...', max_length=40, blank=True)
last_name = models.CharField('...', max_length=80, blank=True)
date_joined = models.DateTimeField('...', default=timezone.now)
previous_login = models.DateTimeField('...', default=timezone.now)
objects = CustomUserManager()
...
def get_profile(self):
if self.type == INTERNAL_USER:
...
return None
def get_or_create_profile(self):
profile = self.get_profile()
if not profile and self.type == INTERNAL_USER:
...
return profile
def update(self, changes):
...
class ExternalUserProxy(User):
objects = CustomUserManager(type=EXTERNAL_USER)
class Meta:
proxy = True
verbose_name = '...'
verbose_name_plural = '...'
class InternalUserProxy(User):
objects = CustomUserManager(type=INTERNAL_USER)
class Meta:
proxy = True
verbose_name = '...'
verbose_name_plural = '...'
def create_profile(sender, instance, created, **kwargs):
if created and instance.type == INTERNAL_USER:
try:
profile = UserProfile()
profile.user = instance
profile.save()
except:
pass
post_save.connect(create_profile, sender=User)
def get_sentinel():
try:
sentinel = User.objects.get(username__exact=SENTINEL_USERNAME)
except User.DoesNotExist:
settings.LOGGER.error("...")
from django.contrib.auth.models import Group
sentinel = User()
sentinel.username = SENTINEL_USERNAME
sentinel.first_name = "..."
sentinel.last_name = "..."
sentinel.set_unusable_password()
sentinel.save()
technical = Group.objects.get(name=GROUP_SUPPORT)
sentinel = User.objects.get(username__exact=SENTINEL_USERNAME)
sentinel.groups.add(technical)
sentinel.save()
return sentinel
corporate / models / __init__.py
...
from .section import Section
...
corporate / models / section.py
from django.conf import settings
from authentication.models import get_sentinel
from .room import Room
class Section(models.Model):
...
boss = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET(get_sentinel), ...)
surrogate = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET(get_sentinel), ...)
room = models.ForeignKey(Room, on_delete=models.SET_NULL, ...)
is_subordinate_to = models.ForeignKey('self', on_delete=models.SET_NULL, ...)
...
What am I doing wrong?
Answers:
You have a circular import.
authentication/models
imports corporate/models
, which imports corporate/models/section
, which imports authentication/models
.
You can’t do that. Rewrite and/or rearrange your modules so that circular imports aren’t needed.
One strategy to do this is to organize your modules into a hierarchy, and make sure that a module only imports other modules that are lower in the hierarchy. (This hierarchy can be an actual directory structure, but it doesn’t have to be; it can just be a mental note in the programmer’s mind.)
For future readers, this can also happen if you name a python file the same name as a dependency your project uses.
For example:
I cannot have a file named retrying.py that is using the retrying package.
Assuming I had the retrying package in my project, I could not have a file called retrying.py with the below contents:
from retrying import retry
print("HI")
A similar error with the message "most likely due to a circular import" would occur.
The same contents would work fine if I renamed the file to "retrying_example1.py"
When importing code from other files, it helps if you spell out the entire subpackage where the thing you want to import comes from. Let’s say you have the following file structure:
mypackage/
subpackage/
__init__.py
helper.py
main/
work.py
If:
__init__.py
imports things from helper.py
(for the end-user to conveniently access)
- and you’re working inside
work.py
- and you need something from
subpackage/helper.py
Then rather than doing:
from ..subpackage import thing_i_need
You should instead do:
from ..subpackage.helper import thing_i_need
For reasonable code, this should help you avoid some of the circular dependency problems, as now you’re no longer relying on __init__.py
to fully finish.
In my case the problem was that I defined the function in the x.py file and in the x.py file I import models from the modals.py file and in the modals.py file I tried to import this function I was trying to set the default value after querying the tables with this function
I received this error when I tried to do a relative import. I had two models files:
utils.models
:
class BaseModel(models.Model):
...
main.models
:
from .models import BaseModel
...
The problem was fixed when, in main.models
, I changed it to:
from utils.models import BaseModel
One way to resolve circular imports is by splitting a file in the circle into multiple files in such a way that the files are no longer importing each other. In this specific case, I think it would be resolved if get_sentinel
was moved to a separate file.
authentication / models_utils.py
def get_sentinel():
...
corporate / models / section.py
from django.conf import settings
from authentication.models_utils import get_sentinel
from .room import Room
class Section(models.Model):
...
I got the same error below:
AttributeError: partially initialized module ‘math’ has no attribute
‘pi’ (most likely due to a circular import)
Because I created math.py
, imported python’s math
module in it and use math.pi
in it as shown below:
# "math.py"
import math
print(math.pi)
So, I changed math.py
to my_math.py
:
# "my_math.py"
import math
print(math.pi)
Then, the error was solved:
3.141592653589793
The order of imports in __init__.py
matters:
models/init.py
from .a import A
from .b import B
a.py
from models.b import B
...
This will give ImportError: cannot import name 'B' from partially initialized module 'models' (most likely due to a circular import) (/models/__init__.py)
To resolve, the import of B
should come before the import of A
in __init__.py
I was getting the same error.
I was doing this:( i.e. importing my models
before blueprint object creation and model uses the db
object defined in the app.py
file. And this main_blueprint is getting registered in app.py.)
from ..models.user_model import User as user_model
main = Blueprint('main', __name__)
I fixed it by importing my model after blueprint object creation.
main = Blueprint('main', __name__)
# always import models after blueprint object creation.
from ..models.user_model import User as user_model
I got this error because I created two controllers clients.py
and users.py
that import from one another, causing circular import
from app.controllers.users import get_user_manager, UserManager
ImportError: cannot import name 'get_user_manager' from partially initialized module 'app.controllers.users' (most likely due to a circular import)
Here is the exact scenario for clarification:
-
The controller client.py
imports get_user_manager
, UserManager
from users.py
to use in its function registerClient
-
Implemented sendForgetPasswordMailClient
in client.py
that does not use the import above
-
In users.py
I called sendForgetPasswordMailClient
from clients.py
that already imports from users.py
, causing circular import
client.py
...
from app.controllers.users import get_user_manager, UserManager
async def registerClient(
client_password: ClientPasswordCreate,
client: UserCreate,
user_db: UserManager = Depends(get_user_manager),
db: Session = Depends(get_async_session)
):
...
async def sendForgetPasswordMailClient(client_mail, client_name, link):
...
users.py
...
from app.controllers.clients import sendForgetPasswordMailClient
class UserManager(BaseUserManager[UserCreate, UserDB]):
...
async def on_after_forgot_password(
self, user: UserDB, token: str, request: Optional[Request] = None
):
link = f'{APP_LINK}?token={token}'
sendForgetPasswordMailClient(user.mail, user.firstName, link)
async def get_user_manager(user_db: SQLAlchemyUserDatabase = Depends(get_user_db)):
yield UserManager(user_db)
The solution was simply to move sendForgetPasswordMailClient
that does not contain any import from users.py
to another file so I can call it freely from users.py
without any issue.
A circular import occurs when two or more modules depend on each other.
Faced this issue and was not sure where the problem was coming from. Took the new logic and added it to its own separate file and it worked because the modules were now separate and independent.
Since this question shows up when googling the error message,
this might be helpful if you’re using type hinting:
from __future__ import annotations # <-still need this.
from typing import TYPE_CHECKING
if TYPE_CHECKING: # <-try this,
from my_module import MyClass # <-if this is only for type hinting.
It’s very easy to get the circular import error ImportError: cannot import name 'MyClass' from partially initialized module 'my_module' (most likely due to a circular import)
if we use type hints, because we import lots of classes. If type hinting is the problem, then the above solution will be helpful.
Note that we still need from __future__ import annotations
even with Python 3.11 (as of 2023), according to the official docs.
I hope this will be helpful to future readers, I had this problem in Django because two models from different apps imported classes from eachother’s model, a quick fix for me was to use dotted import.
Here is an example of what I mean by dotted import:
Given that we have two different apps, namely, app_a and app_b
project/app_a/models.py
class ModelA(models.Mode):
foo=models.CharField(max_length=200)
project/app_b/models.py
class ModelB(models.Model):
bar=models.ForeignKey('app_a.ModelA', on_delete=models.CASCADE)
For some reason I was getting this error when I was trying to print statement inside of class when use streamlit.
Simple and quick workaround solution, Instead of importing the models itself,import the whole file, for example instead of importing "get_sential" model from authentication.models in coprorate.models file import authentication itself and replace get_sential with authentication.models.get_sential
corporate / models / section.py
from django.conf import settings
import authentication
from .room import Room
class Section(models.Model):
...
boss = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET(authentication.models.get_sential), ...)
surrogate = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET(get_sentinel), ...)
room = models.ForeignKey(Room, on_delete=models.SET_NULL, ...)
is_subordinate_to = models.ForeignKey('self', on_delete=models.SET_NULL, ...)
yum install epel-release
dnf remove python3
dnf install python3.11
If you need to reference a model from another app, consider using a string reference. This can help you avoid importing the model directly in modules that are part of the circular import.
service = models.ForeignKey('app1.Model2', on_delete=models.PROTECT)
In my case, the issue happened because I have two lib installation directories and this package was installed on both locations which I think confused python. Problem is solved when I remove one lib location and just use one of them
I’m upgrading an application from Django 1.11.25 (Python 2.6) to Django 3.1.3 (Python 3.8.5) and, when I run manage.py makemigrations
, I receive this message:
File "/home/eduardo/projdevs/upgrade-intra/corporate/models/section.py", line 9, in <module>
from authentication.models import get_sentinel**
ImportError: cannot import name 'get_sentinel' from partially initialized module 'authentication.models' (most likely due to a circular import) (/home/eduardo/projdevs/upgrade-intra/authentication/models.py)**
My models are:
authentication / models.py
from django.conf import settings
from django.contrib.auth.models import AbstractUser, UserManager
from django.db import models
from django.db.models.signals import post_save
from django.utils import timezone
from corporate.constants import GROUP_SUPPORT
from corporate.models import Phone, Room, Section
from library.exceptions import ErrorMessage
from library.model import update_through_dict
from .constants import INTERNAL_USER, EXTERNAL_USER, SENTINEL_USERNAME, SPECIAL_USER, USER_TYPES_DICT
class UserProfile(models.Model):
user = models.OneToOneField(
'User',
on_delete=models.CASCADE,
unique=True,
db_index=True
)
...
phone = models.ForeignKey('corporate.Phone', on_delete=models.SET_NULL, ...)
room = models.ForeignKey('corporate.Room', on_delete=models.SET_NULL, ...)
section = models.ForeignKey('corporate.Section', on_delete=models.SET_NULL, ...)
objects = models.Manager()
...
class CustomUserManager(UserManager):
def __init__(self, type=None):
super(CustomUserManager, self).__init__()
self.type = type
def get_queryset(self):
qs = super(CustomUserManager, self).get_queryset()
if self.type:
qs = qs.filter(type=self.type).order_by('first_name', 'last_name')
return qs
def get_this_types(self, types):
qs = super(CustomUserManager, self).get_queryset()
qs = qs.filter(type__in=types).order_by('first_name', 'last_name')
return qs
def get_all_excluding(self, types):
qs = super(CustomUserManager, self).get_queryset()
qs = qs.filter(~models.Q(type__in=types)).order_by('first_name', 'last_name')
return qs
class User(AbstractUser):
type = models.PositiveIntegerField('...', default=SPECIAL_USER)
username = models.CharField('...', max_length=256, unique=True)
first_name = models.CharField('...', max_length=40, blank=True)
last_name = models.CharField('...', max_length=80, blank=True)
date_joined = models.DateTimeField('...', default=timezone.now)
previous_login = models.DateTimeField('...', default=timezone.now)
objects = CustomUserManager()
...
def get_profile(self):
if self.type == INTERNAL_USER:
...
return None
def get_or_create_profile(self):
profile = self.get_profile()
if not profile and self.type == INTERNAL_USER:
...
return profile
def update(self, changes):
...
class ExternalUserProxy(User):
objects = CustomUserManager(type=EXTERNAL_USER)
class Meta:
proxy = True
verbose_name = '...'
verbose_name_plural = '...'
class InternalUserProxy(User):
objects = CustomUserManager(type=INTERNAL_USER)
class Meta:
proxy = True
verbose_name = '...'
verbose_name_plural = '...'
def create_profile(sender, instance, created, **kwargs):
if created and instance.type == INTERNAL_USER:
try:
profile = UserProfile()
profile.user = instance
profile.save()
except:
pass
post_save.connect(create_profile, sender=User)
def get_sentinel():
try:
sentinel = User.objects.get(username__exact=SENTINEL_USERNAME)
except User.DoesNotExist:
settings.LOGGER.error("...")
from django.contrib.auth.models import Group
sentinel = User()
sentinel.username = SENTINEL_USERNAME
sentinel.first_name = "..."
sentinel.last_name = "..."
sentinel.set_unusable_password()
sentinel.save()
technical = Group.objects.get(name=GROUP_SUPPORT)
sentinel = User.objects.get(username__exact=SENTINEL_USERNAME)
sentinel.groups.add(technical)
sentinel.save()
return sentinel
corporate / models / __init__.py
...
from .section import Section
...
corporate / models / section.py
from django.conf import settings
from authentication.models import get_sentinel
from .room import Room
class Section(models.Model):
...
boss = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET(get_sentinel), ...)
surrogate = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET(get_sentinel), ...)
room = models.ForeignKey(Room, on_delete=models.SET_NULL, ...)
is_subordinate_to = models.ForeignKey('self', on_delete=models.SET_NULL, ...)
...
What am I doing wrong?
You have a circular import.
authentication/models
imports corporate/models
, which imports corporate/models/section
, which imports authentication/models
.
You can’t do that. Rewrite and/or rearrange your modules so that circular imports aren’t needed.
One strategy to do this is to organize your modules into a hierarchy, and make sure that a module only imports other modules that are lower in the hierarchy. (This hierarchy can be an actual directory structure, but it doesn’t have to be; it can just be a mental note in the programmer’s mind.)
For future readers, this can also happen if you name a python file the same name as a dependency your project uses.
For example:
I cannot have a file named retrying.py that is using the retrying package.
Assuming I had the retrying package in my project, I could not have a file called retrying.py with the below contents:
from retrying import retry
print("HI")
A similar error with the message "most likely due to a circular import" would occur.
The same contents would work fine if I renamed the file to "retrying_example1.py"
When importing code from other files, it helps if you spell out the entire subpackage where the thing you want to import comes from. Let’s say you have the following file structure:
mypackage/
subpackage/
__init__.py
helper.py
main/
work.py
If:
__init__.py
imports things fromhelper.py
(for the end-user to conveniently access)- and you’re working inside
work.py
- and you need something from
subpackage/helper.py
Then rather than doing:
from ..subpackage import thing_i_need
You should instead do:
from ..subpackage.helper import thing_i_need
For reasonable code, this should help you avoid some of the circular dependency problems, as now you’re no longer relying on __init__.py
to fully finish.
In my case the problem was that I defined the function in the x.py file and in the x.py file I import models from the modals.py file and in the modals.py file I tried to import this function I was trying to set the default value after querying the tables with this function
I received this error when I tried to do a relative import. I had two models files:
utils.models
:
class BaseModel(models.Model):
...
main.models
:
from .models import BaseModel
...
The problem was fixed when, in main.models
, I changed it to:
from utils.models import BaseModel
One way to resolve circular imports is by splitting a file in the circle into multiple files in such a way that the files are no longer importing each other. In this specific case, I think it would be resolved if get_sentinel
was moved to a separate file.
authentication / models_utils.py
def get_sentinel():
...
corporate / models / section.py
from django.conf import settings
from authentication.models_utils import get_sentinel
from .room import Room
class Section(models.Model):
...
I got the same error below:
AttributeError: partially initialized module ‘math’ has no attribute
‘pi’ (most likely due to a circular import)
Because I created math.py
, imported python’s math
module in it and use math.pi
in it as shown below:
# "math.py"
import math
print(math.pi)
So, I changed math.py
to my_math.py
:
# "my_math.py"
import math
print(math.pi)
Then, the error was solved:
3.141592653589793
The order of imports in __init__.py
matters:
models/init.py
from .a import A
from .b import B
a.py
from models.b import B
...
This will give ImportError: cannot import name 'B' from partially initialized module 'models' (most likely due to a circular import) (/models/__init__.py)
To resolve, the import of B
should come before the import of A
in __init__.py
I was getting the same error.
I was doing this:( i.e. importing my models
before blueprint object creation and model uses the db
object defined in the app.py
file. And this main_blueprint is getting registered in app.py.)
from ..models.user_model import User as user_model
main = Blueprint('main', __name__)
I fixed it by importing my model after blueprint object creation.
main = Blueprint('main', __name__)
# always import models after blueprint object creation.
from ..models.user_model import User as user_model
I got this error because I created two controllers clients.py
and users.py
that import from one another, causing circular import
from app.controllers.users import get_user_manager, UserManager
ImportError: cannot import name 'get_user_manager' from partially initialized module 'app.controllers.users' (most likely due to a circular import)
Here is the exact scenario for clarification:
-
The controller
client.py
importsget_user_manager
,UserManager
fromusers.py
to use in its functionregisterClient
-
Implemented
sendForgetPasswordMailClient
inclient.py
that does not use the import above -
In
users.py
I calledsendForgetPasswordMailClient
fromclients.py
that already imports fromusers.py
, causing circular import
client.py
...
from app.controllers.users import get_user_manager, UserManager
async def registerClient(
client_password: ClientPasswordCreate,
client: UserCreate,
user_db: UserManager = Depends(get_user_manager),
db: Session = Depends(get_async_session)
):
...
async def sendForgetPasswordMailClient(client_mail, client_name, link):
...
users.py
...
from app.controllers.clients import sendForgetPasswordMailClient
class UserManager(BaseUserManager[UserCreate, UserDB]):
...
async def on_after_forgot_password(
self, user: UserDB, token: str, request: Optional[Request] = None
):
link = f'{APP_LINK}?token={token}'
sendForgetPasswordMailClient(user.mail, user.firstName, link)
async def get_user_manager(user_db: SQLAlchemyUserDatabase = Depends(get_user_db)):
yield UserManager(user_db)
The solution was simply to move sendForgetPasswordMailClient
that does not contain any import from users.py
to another file so I can call it freely from users.py
without any issue.
A circular import occurs when two or more modules depend on each other.
Faced this issue and was not sure where the problem was coming from. Took the new logic and added it to its own separate file and it worked because the modules were now separate and independent.
Since this question shows up when googling the error message,
this might be helpful if you’re using type hinting:
from __future__ import annotations # <-still need this.
from typing import TYPE_CHECKING
if TYPE_CHECKING: # <-try this,
from my_module import MyClass # <-if this is only for type hinting.
It’s very easy to get the circular import error ImportError: cannot import name 'MyClass' from partially initialized module 'my_module' (most likely due to a circular import)
if we use type hints, because we import lots of classes. If type hinting is the problem, then the above solution will be helpful.
Note that we still need from __future__ import annotations
even with Python 3.11 (as of 2023), according to the official docs.
I hope this will be helpful to future readers, I had this problem in Django because two models from different apps imported classes from eachother’s model, a quick fix for me was to use dotted import.
Here is an example of what I mean by dotted import:
Given that we have two different apps, namely, app_a and app_b
project/app_a/models.py
class ModelA(models.Mode):
foo=models.CharField(max_length=200)
project/app_b/models.py
class ModelB(models.Model):
bar=models.ForeignKey('app_a.ModelA', on_delete=models.CASCADE)
For some reason I was getting this error when I was trying to print statement inside of class when use streamlit.
Simple and quick workaround solution, Instead of importing the models itself,import the whole file, for example instead of importing "get_sential" model from authentication.models in coprorate.models file import authentication itself and replace get_sential with authentication.models.get_sential
corporate / models / section.py
from django.conf import settings
import authentication
from .room import Room
class Section(models.Model):
...
boss = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET(authentication.models.get_sential), ...)
surrogate = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET(get_sentinel), ...)
room = models.ForeignKey(Room, on_delete=models.SET_NULL, ...)
is_subordinate_to = models.ForeignKey('self', on_delete=models.SET_NULL, ...)
yum install epel-release
dnf remove python3
dnf install python3.11
If you need to reference a model from another app, consider using a string reference. This can help you avoid importing the model directly in modules that are part of the circular import.
service = models.ForeignKey('app1.Model2', on_delete=models.PROTECT)
In my case, the issue happened because I have two lib installation directories and this package was installed on both locations which I think confused python. Problem is solved when I remove one lib location and just use one of them