在这种情况下如何构建日志记录(python)

时间:2016-03-11 15:42:29

标签: python logging

我想知道在特殊情况下构建我的日志的最佳方法是什么。

我有一系列python服务,使用相同的python文件与HW进行通信(例如com.py)。我在这个模块中实现了日志记录,我希望它与调用模块的主服务相关(关联)。

我应该如何构建记录器逻辑,以便如果我有:

  • main_service_1-> module_for_comunication

日志记录转到文件 main_serv_1.log

  • main_service_2-> module_for_comunication

日志记录转到文件 main_serv_2.log

在没有任何东西的情况下,这种情况下的最佳做法是什么?

有没有办法知道导入com.py的文件,以便我能够在com.py中使用此信息来调整日志记录到调用者?

2 个答案:

答案 0 :(得分:1)

根据我的经验,对于这种情况,最干净,最容易实施的策略是将记录器传递给执行记录的代码

因此,为每个要登录其他文件的服务创建一个记录器,并将该记录器传递给通信模块中的代码。您可以使用__name__获取当前模块的名称(实际模块名称,不带.py扩展名)。

在下面的示例中,我实现了在没有传入记录器的情况下的回退。

<强> com.py

from log import setup_logger


class Communicator(object):

    def __init__(self, logger=None):
        if logger is None:
            logger = setup_logger(__name__)

        self.log = logger

    def send(self, data):
        self.log.info('Sending %s bytes of data' % len(data))

<强> svc_foo.py

from com import Communicator
from log import setup_logger


logger = setup_logger(__name__)


def foo():
    c = Communicator(logger)
    c.send('foo')

<强> svc_bar.py

from com import Communicator
from log import setup_logger


logger = setup_logger(__name__)


def bar():
    c = Communicator(logger)
    c.send('bar')

<强> log.py

from logging import FileHandler
import logging


def setup_logger(name):
    logger = logging.getLogger(name)
    handler = FileHandler('%s.log' % name)
    logger.addHandler(handler)
    return logger

<强> main.py

from svc_bar import bar
from svc_foo import foo
import logging


# Add a StreamHandler for the root logger, so we get some console output in
# addition to file logging (for easy of testing). Also set the level for
# the root level to INFO so our messages don't get filtered.
logging.basicConfig(level=logging.INFO)


foo()
bar()

因此,当您执行python main.py时,这就是您将获得的:

在控制台上:

INFO:svc_foo:Sending 3 bytes of data
INFO:svc_bar:Sending 3 bytes of data

svc_foo.logsvc_bar.log每行都有一行

Sending 3 bytes of data

如果Communicator类的客户端使用它而不传入记录器,则日志输出将以com.log(后备)结束。

答案 1 :(得分:0)

我看到了几个选项:

选项1

使用__file____file__是加载模块的文件的路径名(doc)。根据您的结构,您应该能够通过执行os.path.split()来识别模块:

如果文件夹结构是

+- module1
|    +- __init__.py
|    +- main.py
+- module2
     +- __init__.py
     +- main.py

您应该能够使用 main.py 中的代码获取模块名称:

def get_name():
    module_name = os.path.split(__file__)[-2]
    return module_name

这不完全是DRY,因为在 main.py 中需要相同的代码。参考here

选项2

更清洁的是打开2个终端窗口并使用环境变量。例如。您可以在一个终端中将MOD_LOG_NAME定义为MOD_LOG_NAME="main_service_1",在另一个终端中定义MOD_LOG_NAME="main_service_2"。然后,在你的python代码中,你可以使用类似的东西:

import os
LOG_PATH_NAME os.environ['MOD_LOG_NAME']

这是separation of concerns

更新(因为问题有所改进)

一旦建立了不同的名称,您所要做的就是配置记录器:

import logging
logging.basicConfig(filename=LOG_PATH_NAME,level=logging.DEBUG)

(或get_name())并运行程序。