Django日志项目与应用命名空间
我在使用Django的日志功能时遇到了一些问题。顺便说一下,回答这个问题可以帮助我更好地理解Django的命名空间是怎么回事。
这是我项目的结构:
MyProject:
-App1:
....
views.py
-App2:
....
urls.py
settings.py
我想把所有的日志信息都记录到一个文件里。因此,我在settings.py文件中设置了以下的日志记录器:
LOGGING = {
'version': 1,
'disable_existing_loggers': True,
'formatters': {
'verbose': {
#'format': '%(levelname)-8s %(remote_addr)-15s %(path_info)s %(asctime)s %(name)-20s %(funcName)-15s %(message)s'
'format': '%(levelname)-8s %(asctime)s %(name)-20s %(funcName)-15s %(message)s'
},
},
'handlers': {
'normal': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'formatter': 'verbose',
'filename': os.path.join('C:/dev/Instantaneus/Instantaneus/html/static', 'log', 'normal.log')
},
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'verbose',
},
},
'loggers': {
'MyProject': {
'handlers': ['normal','console'],
'level': 'DEBUG',
#'filters': ['request'],
'propagate': True,
},
}
}
在urls.py文件中:
from MyProject.App1.views import EvenementDetailView,
....
url(r'App1/(?P<pk>\d+)/$', login_required(EvenementDetailView.as_view(model=Evenement)), name='evenement_details'),
在App1的views.py文件中:
from django.views.generic import DetailView
import logging
logger = logging.getLogger(__name__)
....
class EvenementDetailView(DetailView):
print __name__
model=Evenement
....
logger.debug('blabla')
当我在浏览器中访问 http://localhost/App1/3
时,控制台中出现了以下内容:
DEBUG 2012-01-18 14:59:04,503 Myproject.evenements.views EvenementDetailView blabla
MyProject.evenements.views
evenements.views
我的问题是,为什么 print __name__
这段代码执行了两次,而且最重要的是,输出的内容不一样?
我猜 DEBUG
日志只出现了一次,因为 evenement.views
不能传播到 MyProject,因为在这种情况下,根是 evenements
。
有没有什么想法?
解决方案,虽然没有深入解释,但它有效:
在我的urls.py中,有一行代码 url(r'App1/(?P<pk>\d+)/activate/$', 'app1.views.activate')
,其中 'activate' 是 App1/views.py 中的一个函数。我把 'App1.views.activate'
改成了 'MyProject.app1.views.activate'
,这样就正常工作了。控制台中只出现了一行 print __name__
的输出。我认为只出现一行是因为 'disable_existing_loggers': True,但我无法解释的是,这个解决方案让我的 views.py 只解析了一次,而不是之前的两次。为了确认这一点,我在文件开头加了一个 print "blabla"
。在第一种情况下,它打印了两次,而在第二种情况下只打印了一次。
1 个回答
温馨提示:我不太确定这是否正确,我的一些观点是基于我很久以前读到的东西,但现在在谷歌上找不到了。
你看到的情况是因为Python导入模块的方式造成的副作用。当一个模块被导入时,它会被放到sys.modules
中。不过,如果可以通过两种不同的路径导入这个模块(在这个例子中,就是有或没有MyProject),那么它可能会被导入两次,每次用不同的__name__
。
解决这个问题的关键是确保MyProject
不在sys.path
中——应该把包含MyProject
的目录放进去,但不要把MyProject
本身放进去。你可以通过启动一个manage.py shell
来验证这一点,确保import evenements
会失败。manage.py
里有一些Django内部的内容,可能会让这个过程变得复杂——不过我上次遇到这个问题是在1.0或1.1版本左右,所以可能已经修复了。
这里有一个深入的讨论:
http://blog.dscpl.com.au/2010/03/improved-wsgi-script-for-use-with.html
这是一篇长文章,可以搜索“两个不同的名字”。