Django - 当文件达到maxBytes时,轮转文件处理器卡住
我在使用Django的RotatingFileHandler时遇到了一个问题。
问题是,当文件达到最大字节数时,它不会创建一个新文件,而是在你尝试使用logger.info("任何信息")时给出错误信息:
奇怪的是:
- 没有人共享日志记录器,视图会有自己的日志记录器,celery的任务也有自己的日志记录器。
日志记录器只在文件顶部初始化一次(chartLogger = getLogger...),同一个文件中的不同函数会使用相同的名称。
Logged from file views.py, line 1561 Traceback (most recent call last): File "C:\Python27\lib\logging\handlers.py", line 77, in emit self.doRollover() File "C:\Python27\lib\logging\handlers.py", line 142, in doRollover os.rename(self.baseFilename, dfn) WindowsError: [Error 32] The process cannot access the file because it is being used by another process
在我的settings.py文件中,我有:
LOGGING = {
'version': 1,
'disable_existing_loggers': True,
'formatters' : {
'standard' : {
'format' : '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
},
},
'handlers': {
'celery.webapp' : {
'level' : 'ERROR',
'class' : 'django.utils.log.AdminEmailHandler',
},
'celery' : {
'level' : 'INFO',
'class' : 'logging.handlers.RotatingFileHandler',
'filename' : 'logs/celery.log',
'maxBytes' : 1024*1024*10, # 10MB
'backupCount' : 10,
'formatter' : 'standard',
},
'views.error' : {
'level' : 'ERROR',
'class' : 'django.utils.log.AdminEmailHandler',
},
'views' : {
'level' : 'INFO',
'class' : 'logging.handlers.RotatingFileHandler',
'filename' : 'logs/views.log',
'maxBytes' : 1024*1024*10, # 10MB
'backupCount' : 10,
'formatter' : 'standard',
},
},
'loggers': {
'celery.webapp' : {
'level' : 'ERROR',
'handlers' : ['celery.webapp'],
'propogate' : True,
},
'celery.webapp.task' : {
'level' : 'INFO',
'handlers' : ['celery'],
'propogate' : True,
},
'views.logger' : {
'level' : 'ERROR',
'handlers' : ['views.error'],
'propogate' : True,
},
'views.logger.login' : {
'level' : 'INFO',
'handlers' : ['views'],
'propogate' : True,
},
'views.logger.register' : {
'level' : 'INFO',
'handlers' : ['views'],
'propogate' : True,
},
'views.logger.chartConfigure' : {
'level' : 'INFO',
'handlers' : ['views'],
'propogate' : True,
},
'views.logger.sendEmail' : {
'level' : 'INFO',
'handlers' : ['views'],
'propogate' : True,
},
},
}
我尝试过更改不同的文件大小,但它在达到maxBytes时就卡住了。
虽然它说进程无法访问文件,因为它正被其他进程使用,但在达到maxBytes之前,所有的日志记录都正常。
编辑:
我已经将日志记录分开,分别用于celery和django。
LOGGING = {
'version': 1,
'disable_existing_loggers': True,
'formatters' : {
'standard' : {
'format' : '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
},
},
'handlers': {
'celery.webapp' : {
'level' : 'ERROR',
'class' : 'django.utils.log.AdminEmailHandler',
},
'celery' : {
'level' : 'INFO',
'class' : 'logging.handlers.RotatingFileHandler',
'filename' : 'logs/celery.log',
'maxBytes' : 1024*1024*10, # 10MB
'backupCount' : 10,
'formatter' : 'standard',
},
'celery_chartConfigure' : {
'level' : 'INFO',
'class' : 'logging.handlers.RotatingFileHandler',
'filename' : 'logs/celery_chartConfigure.log',
'maxBytes' : 1024*1024*10, # 10MB
'backupCount' : 10,
'formatter' : 'standard',
},
'celery_register' : {
'level' : 'INFO',
'class' : 'logging.handlers.RotatingFileHandler',
'filename' : 'logs/celery_register.log',
'maxBytes' : 1024*1024*10, # 10MB
'backupCount' : 10,
'formatter' : 'standard',
},
'views.error' : {
'level' : 'ERROR',
'class' : 'django.utils.log.AdminEmailHandler',
},
'views' : {
'level' : 'INFO',
'class' : 'logging.handlers.RotatingFileHandler',
'filename' : 'logs/views.log',
'maxBytes' : 1024*1024*10, # 10MB
'backupCount' : 10,
'formatter' : 'standard',
},
'views_login' : {
'level' : 'INFO',
'class' : 'logging.handlers.RotatingFileHandler',
'filename' : 'logs/views_login.log',
'maxBytes' : 1024*1024*10, # 10MB
'backupCount' : 10,
'formatter' : 'standard',
},
'views_sendEmail' : {
'level' : 'INFO',
'class' : 'logging.handlers.RotatingFileHandler',
'filename' : 'logs/views_sendEmail.log',
'maxBytes' : 1024*1024*10, # 10MB
'backupCount' : 10,
'formatter' : 'standard',
},
'views_register' : {
'level' : 'INFO',
'class' : 'logging.handlers.RotatingFileHandler',
'filename' : 'logs/views_register.log',
'maxBytes' : 1024*1024*10, # 10MB
'backupCount' : 10,
'formatter' : 'standard',
},
'views_chartConfigure' : {
'level' : 'INFO',
'class' : 'logging.handlers.RotatingFileHandler',
'filename' : 'logs/views_chartConfigure.log',
'maxBytes' : 1024*1024*10, # 10MB
'backupCount' : 10,
'formatter' : 'standard',
},
},
'loggers': {
'celery.webapp' : {
'level' : 'ERROR',
'handlers' : ['celery.webapp'],
'propogate' : True,
},
'celery.webapp.task' : {
'level' : 'INFO',
'handlers' : ['celery'],
'propogate' : True,
},
'celery.webapp.chartConfigure' : {
'level' : 'INFO',
'handlers' : ['celery_chartConfigure'],
'propogate' : True,
},
'celery.webapp.register' : {
'level' : 'INFO',
'handlers' : ['celery_register'],
'propogate' : True,
},
'views.logger' : {
'level' : 'ERROR',
'handlers' : ['views.error'],
'propogate' : True,
},
'views.logger.login' : {
'level' : 'INFO',
'handlers' : ['views_login'],
'propogate' : True,
},
'views.logger.register' : {
'level' : 'INFO',
'handlers' : ['views_register'],
'propogate' : True,
},
'views.logger.chartConfigure' : {
'level' : 'INFO',
'handlers' : ['views_chartConfigure'],
'propogate' : True,
},
'views.logger.sendEmail' : {
'level' : 'INFO',
'handlers' : ['views_sendEmail'],
'propogate' : True,
},
},
}
然而,执行doRollOver时仍然有问题。
把日志分开到celery和Django之间不会解决这个问题吗?因为并不是多个进程在访问日志,而只是Django或Celery。
编辑2:
我还在做Ajax调用。这会不会以某种方式产生另一个进程,从而干扰日志记录?
2 个回答
正如其他回答所说,python manage.py runserver --noreload
是可以用的。但是这里还有一个解决方案,它在代码重新加载时也能正常工作。
在你的 settings.py 文件的最后添加以下内容:
if DEBUG and os.environ.get('RUN_MAIN', None) != 'true':
LOGGING = {}
python manage.py runserver
这个命令会启动一个 Python 进程,来运行你的服务器,并在一个子进程中执行。每当父进程检测到代码有变化时,它就会重新创建一个新的子进程。问题在于,子进程的日志轮换失败,因为父进程仍然在控制那个日志文件。这个解决方案的意思是告诉父进程,日志文件不存在。
我想你遇到的问题和这篇文章描述的一样:Django 使用 RotatingFileHandler 记录日志时出错
简单来说,当你运行 Django 开发服务器时,实际上会有两个进程在同时运行。
默认情况下,Django 服务器会启动两个进程。一个是实际的服务器,另一个是用来检测代码变化并重新加载服务器的。因此,settings.py 文件会被导入两次,这样就导致这两个进程同时访问日志文件。
根据那里的建议,试试
python manage.py runserver --noreload