У меня есть модель, которая вызывает анализатор файлов (для анализа файла), и этот анализатор файлов вызывает модель для сохранения объекта. В настоящее время код выглядит примерно так:
models.py
class Source(models.Model):
...
def parse_file(self):
from ingest.parser import FileParser
...
ingest.py
class FileParser()
def save(self):
from models import Source
...
Это «работает» нормально, однако выполнение импорта в методе сохранения добавляет информацию о 0.25s в первый раз, когда мне приходится его использовать, поскольку он инициализирует импорт. Есть ли лучший способ сделать это?
@VaibhavVishal, иначе это дало бы мне циклическую ошибку импорта.
Вы пробовали использовать функцию get_model, где можно получить модель по строковому имени?
Какое решение вы предпочли из любопытства?
@MadPhysicist Я использовал подход «положить внизу», который вы предложили ниже. Однако существует ли стандартная практика, как это сделать? Например, должны ли вы включать вверху прокомментированный импорт, который говорит что-то вроде «Фактический импорт внизу файла для разрешения циклических зависимостей», или как ваши файлы обычно выглядят так, что его реализуют?






Когда модуль загружается впервые, объект модуля с пустым пространством имен немедленно помещается в sys.modules. Пространство имен заполняется по мере выполнения кода модуля. Любые дальнейшие ссылки на модуль просто извлекают ссылку в sys.modues, независимо от того, полностью он загружен или нет. Это дает два подхода к проблеме.
Способ 1
Поскольку импортированные имена не используются вне методов, вам нужно только убедиться, что они существуют к моменту вызова методов, а не при их первом создании.
Вы можете решить проблему с импортом, поместив неправильный импорт в конец соответствующих файлов. Таким образом, независимо от того, какой модуль загружается первым, все имена верхнего уровня в нем будут инициализированы до того, как другой модуль попытается получить к ним доступ:
models.py
class Source(models.Model):
...
def parse_file(self):
...
from ingest.parser import FileParser
ingest.py
class FileParser()
def save(self):
...
from models import Source
Если models.py загружается первым, строка from ingest.parser import FileParser инициирует загрузку ingest.py, но только после того, как Source будет определен в пространстве имен модуля. Это означает, что from models import Source сможет найти имя. То же самое в обратном порядке.
Если вы знаете, какой модуль всегда будет загружаться первым, то в конец файла нужно переместить только один из импортируемых модулей (тот, который в файле загружается первым).
Способ 2
Более простой альтернативой может быть просто импортировать модули, а не пытаться извлекать из них имена. Это позволит вам сохранить импорт в верхней части файла, поскольку для выполнения циклического импорта будет доступен пустой объект модуля:
models.py
from ingest import parser
class Source(models.Model):
...
def parse_file(self):
# use parser. FileParser
...
ingest.py
import models
class FileParser()
def save(self):
# use models.Source
...
отличный ответ. Большое спасибо за вашу внимательность.
Пожалуйста. Я сталкивался с этой проблемой достаточно раз, когда мог поклясться, что ваш вопрос был дубликатом, но я не могу найти достаточно точное совпадение.
почему бы не импортировать в начало файла, а не внутри метода