我有一个模型,该模型调用文件解析器(以解析文件),并且该文件解析器调用模型以保存对象。当前,代码看起来像这样:
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
...
这种“工作方式”很好,但是在初始化导入时,我第一次使用save方法时在save方法中添加了大约0.25s
。有没有更好的方法来完成上述操作?
答案 0 :(得分:5)
首次加载模块时,具有空名称空间的模块对象将立即放入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
...