uWSGI异步函数不知道Django的日志记录设置

问题描述:

我们正在使用uWSGI来为我们的Django应用程序提供服务。我们还利用uWSGI的mules和假脱机系统定期运行作业,并在请求/响应周期之外异步执行一些任务。uWSGI异步函数不知道Django的日志记录设置

的uWSGI的一部分处理HTTP请求使用Django logging configuration就好了。但是,使用uWSGI的cronmulefunc功能时,通常不会配置记录器 - 您将调用log.error(),异常就会消失。我们发现了一个奇怪的解决方法,我将在下面解释。

这是我们的日志记录设置,在settings.py。 StreamHandler默认路由到stderr,所以我们应该看到DEBUG级别和更高级别的任何日志路由到stderr。

 
LOGGING = { 
    'version': 1, 
    'disable_existing_loggers': True, 
    'formatters': { 
     'verbose': { 
      'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s' 
     }, 
    }, 
    'handlers': { 
     'console': { 
      'level': 'DEBUG', 
      'class': 'logging.StreamHandler', 
      'formatter': 'verbose' 
     } 
    }, 
    'loggers': { 
     '': { 
      'handlers': ['console'], 
      'level': 'NOTSET', 
     } 
    } 
} 

这里有什么行不通的例子:

 
from uwsgidecorators import mulefunc 

log = logging.getLogger(__name__) 

@timer(10, target="mule") 
def test_mule_logging(signum): 
    log.error("You'll never see this message") 

然而,有一个很奇怪的解决方法。如果你导入Django的设置,并且访问它上面的一个键,那么这个记录器会神奇地工作。例如:

 
from django.conf import settings 
getattr(settings, "doesntmatter", None) 

from uwsgidecorators import timer 
import logging 

log = logging.getLogger(__name__) 

@timer(10, target="mule") 
def test_mule_logging(signum): 
    log.error("I WILL see this log!") 

虽然这看起来像一个可怕的解决方法。

我认为你描述的行为是有意义的。

在常规的工人,uwsgi加载一个WSGI应用程序,使Django的负载设置,并作为该部分配置全局的Python日志系统。由django应用程序运行并包含日志记录语句的库代码最终由日志记录配置处理(而不必知道django是否存在或配置了日志记录系统)。

在骡子,uwsgi只运行你给它的代码,而不是正式工定义的WSGI模块/脚本,所以没有什么是配置日志系统。骡子仍然是相同的环境(UID,GID,CHDIR,virtualenv中,PYTHONPATH,ENV瓦尔像DJANGO_SETTINGS_MODULE)内运行,因此调用django.setup()(或django.configure_settings)将导入您的设置,并配置全球记录系统(全球到Python的过程,是骡工),修理您的日志记录呼叫。

最后一块拼图:django.conf.settings模块是一个特殊的懒惰对象,因此它可以在django完成自我配置之前通过各种模块导入,并推迟真正加载设置,直到尝试访问模块属性为止。在现代Django版本中可以更加明确地获得这种行为,其中django.setup()