Django日志项目与应用命名空间

0 投票
1 回答
1913 浏览
提问于 2025-04-17 10:31

我在使用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 个回答

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

这是一篇长文章,可以搜索“两个不同的名字”。

撰写回答