【问题标题】:Django - Rotating File Handler stuck when file is equal to maxBytesDjango - 当文件等于 maxBytes 时,旋转文件处理程序卡住
【发布时间】:2014-12-28 05:31:54
【问题描述】:

我对 Django 的 RotatingFileHander 有疑问。

问题是当文件达到 maxBytes 大小时,它不会创建新文件,并在您尝试执行 logger.info("any message") 时给出错误消息:

奇怪的是:

  1. 没有人共享记录器,视图有自己的记录器,来自 celery 的任务有自己的记录器。
  2. 记录器仅在文件顶部启动一次(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 调用。这会以某种方式产生另一个可能会干扰日志记录的进程吗?

【问题讨论】:

    标签: python django


    【解决方案1】:

    我猜你正面临这篇文章中描述的问题:Django logging with RotatingFileHandler error

    即运行Django开发服务器时,实际上有两个进程在运行。

    默认情况下,Django 服务器的两个进程正在运行。一个是 实际的服务器,而另一个是检测代码的变化和 重新加载服务器。因此,settings.py 被导入两次,并且 因此两个进程同时访问日志文件 时间。

    按照那里的建议,尝试

    python manage.py runserver --noreload
    

    【讨论】:

      【解决方案2】:

      如其他答案中所述,python manage.py runserver --noreload 将起作用。但这是另一个仍然适用于代码重新加载的解决方案。

      在你的 settings.py 末尾添加这个

      if DEBUG and os.environ.get('RUN_MAIN', None) != 'true':
          LOGGING = {}
      

      python manage.py runserver 启动一个 python 进程,在子 python 进程中启动你的服务器。每次父项检测到更改时,它都会重新创建一个新子项。问题是子进程的日志轮换失败,因为父进程仍然拥有该文件的句柄。此解决方案告诉父级没有日志文件。

      【讨论】:

      • 谢谢,下次试试这个
      • 这就像一个魅力谢谢。在我的桌面上开发时必须切换到--noreload 或删除我的日志轮换,这是一个 PITA。
      • 不错。请参阅 autoreload.py 以了解其工作原理。
      • @djvg - 我最初很困惑,因为要设置的变量的名称是DJANGO_AUTORELOAD_ENV。但后来我意识到这实际上是一个字符串变量,等于'RUN_MAIN'
      猜你喜欢
      • 1970-01-01
      • 2015-12-23
      • 1970-01-01
      • 1970-01-01
      • 2015-05-29
      • 1970-01-01
      • 1970-01-01
      • 2021-04-26
      • 1970-01-01
      相关资源
      最近更新 更多