Python Django: ImportError: cannot import name '...' from partially initialized module '...' (скорее всего, из-за циклического импорта) (......)
В проекте Django мне нужно импортировать класс-A из файла-1 в файл-2. и импортировать класс-B из файла-2 в файл-1.
У этих классов есть свои уникальные методы, и я хочу использовать эти методы в другом файле (как описано выше).
Я работаю с:
Python 3.8.10 (в виртуальной среде)
Windows 10 - 64 бит (последняя сборка)
Django 4.0.4
Когда я запускаюpython manage.py runserver
, я вижу следующие ошибки:
(my_ea_proj) PS F:\my_ea_proj\ea_proj> python.exe .\manage.py runserver
Traceback (most recent call last):
File ".\manage.py", line 30, in <module>
main()
File ".\manage.py", line 13, in main
django.setup()
File "F:\my_ea_proj\lib\site-packages\django\__init__.py", line 24, in setup
apps.populate(settings.INSTALLED_APPS)
File "F:\my_ea_proj\lib\site-packages\django\apps\registry.py", line 116, in populate
app_config.import_models()
File "F:\my_ea_proj\lib\site-packages\django\apps\config.py", line 304, in import_models
self.models_module = import_module(models_module_name)
File "C:\Python38\lib\importlib\__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
File "<frozen importlib._bootstrap>", line 991, in _find_and_load
File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 848, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "F:\my_ea_proj\ea_proj\ea_app\models.py", line 16, in <module>
from .login_request_based import full_request
File "F:\my_ea_proj\ea_proj\ea_app\login_request_based.py", line 10, in <module>
from ea_app.all_utils.ea_utils import ea_utils_class
File "F:\my_ea_proj\ea_proj\ea_app\all_utils\ea_utils.py", line 10, in <module>
from ea_app.login_request_based import full_request
ImportError: cannot import name 'full_request' from partially initialized module 'ea_app.login_request_based' (most likely due to a circular import) (F:\my_ea_proj\ea_proj\ea_app\login_request_based.py)
F:\my_ea_proj\ea_proj>tree /F
F:.
│ manage.py
│ __init__.py
│
├───ea_app
│ │ admin.py
│ │ apps.py
│ │ login_request_based.py
│ │ models.py
│ │ tasks.py
│ │ tests.py
│ │ urls.py
│ │ views.py
│ │ __init__.py
│ │
│ ├───all_utils
│ │ ea_remote_db.py
│ │ ea_utils.py
│ │ __init__.py
│ │
│ ├───migrations
│ │ __init__.py
│ | ...skipped other migration files...
│
└───ea_proj
asgi.py
settings.py
urls.py
wsgi.py
__init__.py
Когда я добавляю следующие классы в файлы ea_utils.py
и login_request_based.py
, я получаю ошибку ImportError: cannot import name 'full_request' from partially initialized module 'ea_app.login_request_based' (most likely due to a circular import)...
. Но когда я комментирую один из них, проблема исправляется и встроенный веб-сервер запускается успешно.
F:\my_ea_proj\ea_proj\ea_app\all_utils\ea_utils.py:
from ea_app.login_request_based import full_request
F:\my_ea_proj\ea_proj\ea_app\login_request_based.py
from ea_app.all_utils.ea_utils import ea_utils_class
Как решить эту проблему?
Я столкнулся с той же проблемой со следующей структурой файла:
├───models
│ │ app_1.py
│ │ __init__.py # (will refer to this as models.init)
│ │
│ ├───engines
│ │ app_2.py
│ │ __init__.py
Итак, в models.init
у меня был экземпляр из app_2
следующим образом
from models.engines.app_2 import app2_class
new_app = app2_class()
new_app.do_something()
В моем модуле app_1
у меня были такие импорты:
from models import new_app
В моем модуле app_2
у меня были такие импорты:
from models.app_1 import app1_class
Я попробовал несколько обходных путей, но ни один из них не сработал, но я смог избавиться от ошибки и заставить все классы и экземпляр в models.init
работать правильно.
Вот окончательное решение, которое мне удалось найти.
Никаких изменений в models.init
, так как мне нужен доступ к нему.
Нет изменений в app_2
также.
В моем модуле app_1
я модифицировал его следующим образом:
import models
# Somewhere in the code, I went with
models.new_app.do_something_different()
Надеемся, что это сработает для вас.
У меня была очень похожая проблема, как ни странно, я выделил классы, которые мне нужно было импортировать, в отдельный файл моделей (models_3.py), и импорт оттуда работал для меня, я все еще не знаю, почему это происходит, потому что у меня есть другие модели. они работают таким образом, но, похоже, есть особые случаи.
Старая структура:
├───app
│ │ models_1.py
│ ├ models_2.py
│ │ __init__.py
новая структура:
├───app
│ │ models_1.py
│ ├ models_2.py
│ ├ models_3.py
│ │ __init__.py
Если в одном из модулей вы импортируете модель только для того, чтобы сделать отношение к ней, например:
from characters.models import Character
class Inventory(models.Model):
character = models.OneToOneField(Character, on_delete=models.CASCADE, related_name='inventory')
Вы можете сделать это и таким образом убрать import
в начале:
#from characters.models import Character # Becomes useless
class Inventory(models.Model):
character = models.OneToOneField('characters.Character', on_delete=models.CASCADE, related_name='inventory')
Я не знаю, является ли мое новое решение трюком или это принцип работы Python во фреймворке Django.
- Django==4.0.X или 3.2.X
- Python=3.8.10
- windows==10 x64 (последняя сборка)
Пожалуйста, внимательно посмотрите на вывод моей команды, о которой идет речь (F:\my_ea_proj\ea_proj>tree /F
). и внимательно прочитайте мой вопрос.
Когда я добавляю from ea_app.models import BotReport
в файл ea_utils.py
, внутри основного блока python (рядом со строками, относящимися к import ...
или from ... import ...
), я получаю ошибку ниже:
.....skipped.....
Файл "F:\my_ea_proj\ea_proj\ea_app\all_utils\ea_utils.py", строка 50, in module
from ea_app.models import BotReport ImportError: cannot import name 'BotReport' from partially initialized module 'ea_app.models'
(скорее всего, из-за циклического импорта) (F:\my_ea_proj\ea_proj\ea_app\models.py)
но когда я добавляю from ea_app.models import BotReport
в секции метода класса(ов), все работает без проблем. например:
class EA_UTILS_CLASS (object):
def get_transfers (self, bot_id: int):
from ea_app.models import BotReport
....skipped....
....skipped....
tmpObj = BotReport.objects.get (id=bot_id)
tmpObj.transfer.create(.........)
Надеюсь, мое решение поможет другим разработчикам Django+Python.
Доброго времени суток ;X