Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 两次导入的模块会在其中的对象上重新创建_Python_Django - Fatal编程技术网

Python 两次导入的模块会在其中的对象上重新创建

Python 两次导入的模块会在其中的对象上重新创建,python,django,Python,Django,我有一个Django项目。Django项目的一部分是一个报告模块,它在所有已安装的应用程序中搜索报告目录,非常类似于管理界面的自动发现机制 这个模块有一个小的Registry类,用于注册找到的类。以一种非常简单的方式,它看起来像这样: def autodiscover(): """ Searches for reports module in all INSTALLED_APPS """ global REPORTSLOADING if REPORTSL

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

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

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()
如果任何已安装的应用程序需要注册报表类,我们需要在
reports/\uuuuuu init\uuuuuuuuu.py
中添加一行:

import reports
reports.registery.register(SomeReportClass)
在main url.py中,我将执行以下操作:

import reports
reports.autodiscover()


urlpatterns = patterns('',
....

 (r'', include(reports.registery.urls)),
)
现在我决定为它创建一个可插入的django应用程序,并将相同的代码放在包的
\uuuu init\uuuuuuuuuuy.py
中。我面临的问题是,具有新结构的报表模块会被导入两次,从而导致“Registry”对象的重新创建。因此,实际上没有注册URL。它从url.py内部的导入加载一次(如预期的那样),另一次由autodiscover启动。我已通过以下方式对此进行了验证:

print hex(id(registery))
发现它返回了两个不同的值

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


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

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

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

  • settings.py文件实际上导入了两次

  • 修正:

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

  • 不要从settings.py导入模块


  • 这不是Python中导入的工作方式;再次导入模块只会返回现有的模块对象。在
    sys.modules
    结构中获得两次模块的唯一方法是,如果模块是以两个不同的名称导入的,或者是通过指向
    bar.py
    )的符号链接(
    foo.py
    )导入的,或者是将模块用作主python脚本(
    python bar.py
    ),然后再次导入(
    import bar
    );在这种情况下,模块既是
    bar
    又是
    \uuuu main\uuuuu
    。你可以随意忽略一个迂腐的挑剔:它拼写为“registry”:-PI假设它是用不同的名称导入的,这就是我检查导入的原因。根据我做的检查,它只导入了两次,相同的名称,但不同的对象。感谢学究式的检查:)根据我的检查,模块没有以不同的名称导入。有没有一种方法可以打印出导入模块的内容来确保?真的吗?是否有嵌套命名空间?呃。我现在把导入改为“projectname.reports”,效果很好。仍然不知道为什么“导入报告”本身不起作用!