导入两次的模块会导致其内部对象重新创建

时间:2013-02-11 16:03:01

标签: python django

我有一个Django项目。这个Django项目的一部分是一个报告模块,它在所有INSTALLED_APPS中搜索报告目录,非常类似于管理界面的自动发现机制。

这个模块有一个小的注册类,可以注册找到的类。以非常简单的方式看起来像这样:

def autodiscover():
    """
    Searches for reports module in all INSTALLED_APPS
    """

    global REPORTSLOADING
    if REPORTSLOADING:
        return
    REPORTSLOADING = True

    import imp
    from django.conf import settings

    for app in settings.INSTALLED_APPS:
        try:
            app_path = import_module(app).__path__
        except AttributeError:
            continue

        try:
            imp.find_module('reports', app_path)
        except ImportError:
            continue

        import_module("%s.reports" % app)
    REPORTSLOADING = False

class ReportsRegistery(object):
      .....

registery = ReportsRegistery()

如果任何INSTALLED_APPS需要注册一个Report类,我们需要reports/__init__.py内的一行:

import reports
reports.registery.register(SomeReportClass)

在主urls.py中,我会这样做:

import reports
reports.autodiscover()


urlpatterns = patterns('',
....

 (r'', include(reports.registery.urls)),
)

现在我决定为它创建一个可插入的django应用程序,并将相同的代码放在包的__init__.py中。我面临的问题是具有新结构的报告模块被导入两次,从而导致重新创建“registery”对象。因此,实际上没有注册网址。它从urls.py中的导入(如预期)加载一次,另一次由自动发现启动。我通过以下方式验证了这一点:

print hex(id(registery))

并发现它返回了2个不同的值。

我认为报告包将被导入一次,就像它只是一个模块一样。

如何防止它被加载两次?或者,我如何确保只有一个ReportsRegistery实例可以使用?

1 个答案:

答案 0 :(得分:0)

Django两次导入模块的情况并不少见。这有两个原因:

  1. 经典的Django项目布局鼓励您在两个不同的位置将路径上的工作目录放在两次。这意味着您可以导入project.moduleapp.project.module的内容,这会混淆导入机制。

  2. settings.py文件实际上已导入两次。

  3. 修正:

    1. 仔细检查所有导入是否使用相同的路径样式。

    2. 请勿从settings.py

    3. 导入您的模块