Python 两次导入的模块会在其中的对象上重新创建
我有一个Django项目。Django项目的一部分是一个报告模块,它在所有已安装的应用程序中搜索报告目录,非常类似于管理界面的自动发现机制 这个模块有一个小的Registry类,用于注册找到的类。以一种非常简单的方式,它看起来像这样:Python 两次导入的模块会在其中的对象上重新创建,python,django,Python,Django,我有一个Django项目。Django项目的一部分是一个报告模块,它在所有已安装的应用程序中搜索报告目录,非常类似于管理界面的自动发现机制 这个模块有一个小的Registry类,用于注册找到的类。以一种非常简单的方式,它看起来像这样: def autodiscover(): """ Searches for reports module in all INSTALLED_APPS """ global REPORTSLOADING if REPORTSL
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两次导入模块并不少见。原因有两个:
project.module
,或者导入为app.project.module
,这会混淆导入机制这不是Python中导入的工作方式;再次导入模块只会返回现有的模块对象。在
sys.modules
结构中获得两次模块的唯一方法是,如果模块是以两个不同的名称导入的,或者是通过指向bar.py
)的符号链接(foo.py
)导入的,或者是将模块用作主python脚本(python bar.py
),然后再次导入(import bar
);在这种情况下,模块既是bar
又是\uuuu main\uuuuu
。你可以随意忽略一个迂腐的挑剔:它拼写为“registry”:-PI假设它是用不同的名称导入的,这就是我检查导入的原因。根据我做的检查,它只导入了两次,相同的名称,但不同的对象。感谢学究式的检查:)根据我的检查,模块没有以不同的名称导入。有没有一种方法可以打印出导入模块的内容来确保?真的吗?是否有嵌套命名空间?呃。我现在把导入改为“projectname.reports”,效果很好。仍然不知道为什么“导入报告”本身不起作用!