gpt4 book ai didi

python - 项目的结构化日志记录

转载 作者:行者123 更新时间:2023-11-28 17:28:51 25 4
gpt4 key购买 nike

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

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

我想根据与 3 个主要脚本相关联的文件来组织我的日志记录,所以我想要:acquisition.log、actuation.log 和 management.log。在此日志中,我希望从对 network.py 和 device.py 的调用中获得相应的日志(使用命名空间 %(name))

示例(采集日志):

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< 中看到/strong>.

我实现此目的的方法是使用记录器功能在我记录的每个文件中创建后备记录器。而且,稍后如果我想从该文件中记录信息,我会在主脚本文件中更改在导入文件中创建的记录器。

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

acquisition.py(主脚本):

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:

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:

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:

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

目标?

  • 我想知道是否有更优雅的解决方案,不使用将记录器作为参数传递给调用的方法的逻辑。

  • 我想了解在更复杂的情况下,例如在使用外部模块时,日志记录的结​​构通常是怎样的。

  • 而且,我想阅读对这种日志记录策略的批评。

提前致谢

最佳答案

你应该研究官方logging cookbook以及一些可以正确记录日志的复杂项目。我建议阅读 requests source code了解一个相当复杂的项目如何进行日志记录。

对于您的案例,食谱中的关键内容可能是:

Multiple calls to logging.getLogger('someLogger') return a reference to the same logger object. This is true not only within the same module, but also across modules as long as it is in the same Python interpreter process.

一个典型的方法是在文件的顶部有类似下面的内容:

import logging
log = logging.getLogger(__name__)

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

def add(x, y):
log.debug('Adding {} and {}'.format(x, y))
return x + y

如果您正在创建一些长期运行的服务并打算记录所有/大多数/许多函数调用,请考虑使用装饰器。我建议 this post from the Fresh Books Dev Blog作为使用装饰器进行日志记录的介绍。听起来您的程序可能会受益于装饰器方法。

关于python - 项目的结构化日志记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36205426/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com