我正在开发一个Django应用程序,我试图用错误/跟踪日志记录Python的日志记录模块.理想情况下,我希望为站点的不同区域配置不同的记录器.到目前为止,我已经完成了所有这些工作,但有一件事让我摸不着头脑.
我有根记录器转到sys.stderr,我已经配置了另一个记录器来写入文件.这是在我的settings.py文件中:
sviewlog = logging.getLogger('MyApp.views.scans') view_log_handler = logging.FileHandler('C:\\MyApp\\logs\\scan_log.log') view_log_handler.setLevel(logging.INFO) view_log_handler.setFormatter(logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s')) sviewlog.addHandler(view_log_handler)
看起来很简单.不过这是问题所在:无论我写入sviewlog还是写入日志文件两次.根记录器只打印一次.就像addHandler()被调用两次一样.当我将代码放入调试器时,这正是我所看到的.settings.py中的代码执行两次,因此创建了两个FileHandler并将其添加到同一个logger实例中.但为什么?我该如何解决这个问题呢?
谁能告诉我这里发生了什么?我已经尝试将sviewlog记录器/处理程序实例化代码移动到它所使用的文件中(因为这实际上对我来说似乎是合适的地方),但我有同样的问题.我在网上看到的大多数例子都只使用根记录器,而我更喜欢使用多个记录器.
请允许我回答我自己的问题.这里的根本问题是settings.py被导入两次,甚至更多(见这里).(我仍然不明白为什么会这样.也许一些Django专家可以向我解释.)这似乎也适用于其他一些模块.在这一点上,我认为假设将导入settings.py的次数是不明智的.就此而言,这种假设一般不安全.我在settings.py以外的地方有这个代码,结果很相似.
你必须围绕这个编码.也就是说,在向其添加其他处理程序之前,您必须检查记录器中的现有处理程序.这有点难看,因为将多个处理程序(即使是相同类型)连接到一个记录器是完全合理的.有一些解决方案可以解决这个问题.一个是检查记录器对象的处理程序属性.如果您只需要一个处理程序且长度> 0,则不要添加它.就个人而言,我不喜欢这个解决方案,因为它会让更多处理程序变得混乱.
我更喜欢这样的东西(感谢Thomas Guettler):
# file logconfig.py if not hasattr(logging, "set_up_done"): logging.set_up_done=False def set_up(myhome): if logging.set_up_done: return # set up your logging here # ... logging.set_up_done=True
我必须说,我希望Django多次导入settings.py更好地记录下来.而且我会想象我的配置会以某种方式导致这种多重导入,但我无法找到导致问题的原因以及原因.也许我只是在他们的文档中找不到,但我认为这是你需要警告用户的事情.
从版本1.3开始,Django使用标准的python日志记录,配置了LOGGING
设置(此处记录:1.3,dev).
Django日志参考:1.3,dev.
很难对您的具体案例发表评论.如果settings.py执行两次,那么每发送一次日志就会得到两行是正常的.
我们遇到了同样的问题,所以我们在项目中设置了一个专门用于记录的模块.那些模块有一个"模块单例"模式,所以我们只执行一次有趣的代码.
它看起来像这样:
def init_logging(): stdoutHandler = logging.StreamHandler( sys.stdout ) stdoutHandler.setLevel( DEBUG ) stdoutHandler.setFormatter( logging.Formatter( LOG_FORMAT_WITH_TIME ) ) logging.getLogger( LOG_AREA1 ).addHandler( stdoutHandler ) logInitDone=False #global variable controlling the singleton. if not logInitDone: logInitDone = True init_logging()
首次导入log.py将正确配置日志记录.
恢复旧线程,但在使用dictConfig格式的 Django 1.3 Python日志记录时,我遇到了重复的消息.
在disable_existing_loggers
摆脱了重复处理/记录的问题多settings.py负载的,但你仍然可以得到重复的日志消息,如果你不指定propagate
适当的具体布尔logger
.即,确保propagate=False
为子记录器设置.例如,
'loggers': { 'django': { 'handlers':['null'], 'propagate': True, 'level':'INFO', }, 'django.request': { 'handlers': ['console'], 'level': 'ERROR', 'propagate': False, }, 'project': { 'handlers': ['console', 'project-log-file'], 'level': 'DEBUG', 'propagate': True, }, 'project.customapp': { 'handlers': ['console', 'customapp-log-file'], 'level': 'DEBUG', 'propagate': False, }, }
在这里project.customapp
设置,propagate=False
以便它也不会被project
记录器捕获.在Django的记录文档都非常出色,一如既往.
回答关于为什么"Django多次导入settings.py"的问题:它没有.
实际上,它确实会被导入两次(跳过第一个代码块以进入它,但如果你有时间则读取一个好的):
http://blog.dscpl.com.au/2010/03/improved-wsgi-script-for-use-with.html
PS-抱歉恢复旧线程.