我在我的python项目上使用Logging。 我的问题是关于在我的项目中构建日志记录的正确和优雅的方法,因为我将首先描述我正在使用的结构。
我有3个主要的.py脚本,所以在启动时称为服务的acquisition.py,actus.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.thread 和 acquisition.devices <中看到它/强>
我实现这一点的方法是使用记录器功能,我用它在每个文件中创建一个后备记录器,我正在记录。并且,稍后如果我想记录该文件中的信息,我会在主脚本文件中更改导入文件中创建的记录器。
解释上述内容的代码示例:
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...
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...
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...
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
我想知道是否有更优雅的解决方案,不使用将记录器作为参数传递给被调用方法的逻辑。
我想了解在更复杂的情况下,例如在使用外部模块时,日志记录的结构通常是什么。
而且,我想阅读关于这种采伐策略的评论家。
提前谢谢
答案 0 :(得分:2)
您应该学习官方logging cookbook和一些正确记录的复杂项目。我建议阅读requests source code以了解一个相当复杂的项目如何进行记录。
对你的案子来说,食谱的关键点可能是:
对logging.getLogger(&#39; someLogger&#39;)的多次调用会返回一个引用 到同一个记录器对象。不仅在同一个地方也是如此 模块,但也可以跨模块,只要它在同一个Python中 翻译过程。
一种典型的方法是在文件顶部添加以下内容:
.plot()
这会使import logging
log = logging.getLogger(__name__)
成为全局,因此可以在函数中使用它而不传递log
作为参数:
log
如果您正在创建一些长时间运行的服务并打算记录所有/大多数/多个函数调用,请考虑使用装饰器。我建议this post from the Fresh Books Dev Blog作为使用装饰器进行日志记录的介绍。听起来您的程序可能会受益于装饰器方法。