首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >项目的结构化日志记录

项目的结构化日志记录
EN

Stack Overflow用户
提问于 2016-03-24 16:37:38
回答 1查看 2.2K关注 0票数 3

我在python项目中使用日志记录。我的问题是关于在我的项目中构造日志记录的正确和优雅的方法,因为我将首先描述我正在使用的结构。

我有3个主要的.py脚本,即acquisition.py、actuation.py和management.py,它们在启动时被称为服务。上面的三个脚本导入network.py和devices.py。

我想组织与三个主脚本相关联的每个文件的日志记录,所以我希望有: acquisition.log、actuation.log和management.log。在这些日志中,我希望拥有调用network.py a device.py (使用命名空间%(名称))的相应日志。

示例(acquisition.log):

代码语言:javascript
复制
INFO acquisition.thread 2016-03-17 12:26:02,069 in Thread 70de3b66-e14b-11e5-8953-80fa5b0ae007
DEBUG acquisition 2016-03-17 12:26:02,070 Thread launched 70de3b66-e14b-11e5-8953-80fa5b0ae007
INFO acquisition.devices 2016-03-17 12:26:03,072  Variable_R read:  0013a20040c1bb0b  temperature1
ERROR acquisition.devices 2016-03-17 12:26:19,076 variable.read.DeviceConfigurationError: 0013a20040c1bb0b 
INFO acquisition.thread 2016-03-17 12:26:19,077 exit Thread 70ddfa20-e14b-11e5-8953-80fa5b0ae007
ERROR acquisition.devices 2016-03-17 12:26:25,085 variable.read.DeviceConfigurationError: 0013a20040c1bb0b 
INFO acquisition.thread 2016-03-17 12:26:25,086 exit Thread 70de3b66-e14b-11e5-8953-80fa5b0ae007

在本例中,您可以看到对于同一个日志文件,我可以从不同的文件中进行日志记录,它可以在日志名称空间acquisition.threadacquisition.devices.中看到。

我实现这一目标的方法是拥有一个记录器函数,用于在每个文件中创建一个后备记录器,我将在其中进行日志记录。然后,如果我想记录该文件中的信息,我将在主脚本文件中修改导入文件中创建的记录器。

解释上述内容的代码示例:

acquisition.py (主脚本):

代码语言:javascript
复制
imports...
import logger_sys
import logging
import xnetwork
import xdevices

# Log configuration
log_name = os.path.basename(__file__).strip(".py")
logit = logger_sys.setup_logger(log_name, log_name) #internal logger for main file
logger_thread = logging.getLogger(log_name + '.thread')

#Log configuration of external files
xnetwork.logger = logging.getLogger(log_name + '.network')
xdevices.logger = logging.getLogger(log_name + '.devices')

logit.info("START acquisition_service")

# REST OF THE CODE... 

xdevices.py:

代码语言:javascript
复制
import logger_sys

# Fallback logger in case the calling script doesnt modify logger
log_name = __name__.strip(".py") + '_fallback'
logger = logger_sys.setup_logger(log_name, log_name, stream_hdlr=False)

# REST OF THE CODE...

xnetworks.py:

代码语言:javascript
复制
import logger_sys

# Fallback logger in case the calling script doesnt modify logger
log_name = __name__.strip(".py") + '_fallback'
logger = logger_sys.setup_logger(log_name, log_name, stream_hdlr=False)

# REST OF THE CODE...

logger_sys.py:

代码语言:javascript
复制
import logging, sys, os
from global_settings import RUNNING_MODE, DEBUG, STAGING, PRODUCTION

def setup_logger(namespace, filename, stream_hdlr=True):

    logger = logging.getLogger(namespace)

    handler_format = logging.Formatter("%(levelname)s %(name)s %(asctime)s %(message)s")

    log_handler = logging.FileHandler(filename + ".log")
    logger.addHandler(log_handler)
    log_handler.setFormatter(handler_format)

    if RUNNING_MODE == DEBUG:
        if stream_hdlr:
            log_handler = logging.StreamHandler(sys.stdout)
            logger.addHandler(log_handler)
            log_handler.setFormatter(handler_format)

        logger.setLevel(logging.DEBUG)

    elif RUNNING_MODE == STAGING or RUNNING_MODE == PRODUCTION:
        logger.setLevel(logging.INFO)

    return logger

目标?

  • 我想知道是否有更优雅的解决方案,在调用的方法中不使用传递记录器作为参数的逻辑。
  • 我想了解在更复杂的情况下,例如在使用外部模块时,日志记录通常是如何构造的。
  • 而且,我想读一下关于伐木策略的批评意见。

提前谢谢你

EN

回答 1

Stack Overflow用户

发布于 2016-03-24 18:13:32

您应该学习官方的伐木食谱和一些正确记录日志的复杂项目。我建议阅读请求源代码,看看一个相当复杂的项目是如何进行日志记录的。

也许从你的烹饪书中得到的关键是:

对logging.getLogger('someLogger')的多次调用返回对同一个记录器对象的引用。这不仅在同一个模块中是正确的,而且在相同的Python解释器进程中跨模块也是如此。

一种典型的方法是在文件的顶部设置如下内容:

代码语言:javascript
复制
import logging
log = logging.getLogger(__name__)

这使得log是全局的,因此可以在函数中使用它,而无需将log作为参数传递:

代码语言:javascript
复制
def add(x, y):
    log.debug('Adding {} and {}'.format(x, y))
    return x + y

如果您正在创建一些长期运行的服务,并且打算记录所有/大部分/多个函数调用,请考虑使用装饰器。我建议使用这篇文章来自“新鲜图书开发”博客作为使用装饰器进行日志记录的介绍。听起来您的程序可能会从装饰方法中受益。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36205426

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档