如何为每个线程创建自己的日志记录实例?

时间:2014-09-28 19:48:16

标签: python multithreading logging

例如,我有这些文件包含我想要使用的类(仅示例,可能不起作用)

# helper_one.py

import logging

logger = logging.getLogger('HelperOne')

class HelperOne:
    def __init__(self, data):
        self.data = data

    def run(self):
        logger.debug('HelperOne::Run function with data: ' + self.data)
        return True

# controller_one.py

import logging

from helper_one import HelperOne

logger = logging.getLogger('ControllerOne')

class ControllerOne:
    def __init__(self, data):
        self.data = data

    def run(self):
        logger.debug('ControllerOne::Run function with data: ' + self.data)

        ho = HelperOne(self.data + '_data')
        return ho.run()

我有一个创建线程的文件

import logging 

from controller_one import ControllerOne

# this function creates threads (its just an example)
def run_task(task_id, data):
    logging.basicConfig(
        filename=os.path.join('logs', str(task_id) + '.log'),
        level=logging.DEBUG,
        format='%(asctime)s\t%(name)s\t%(levelname)s\t%(message)s'
    )

    result = ControllerOne(data)

    logging.debug('run_task: ' + result)

如果我在我的示例中创建日志记录实例,则所有日志都写在一个文件中。 对于每个线程,如何通过记录到自己的文件来创建自己的日志记录实例?

此致,Alex。

1 个答案:

答案 0 :(得分:6)

记录器名称(传递给getLogger函数的字符串)可以是您想要的任何内容。正如the docs解释:

  

name可能是一个以句点分隔的层次结构值,例如foo.bar.baz(例如,它也可能只是普通foo)。在分层列表中较低的记录器是列表中较高的记录器的子项。例如,给定名称为foo的记录器,名称为foo.barfoo.bar.bazfoo.bam的记录器都是foo的后代。记录器名称层次结构类似于Python包层次结构,如果您使用建议的构造logging.getLogger(__name__)按模块组织记录器,则与其相同。那是因为在模块中,__name__是Python包命名空间中的模块名称。

因此,使用__name__作为名称​​推荐,但不是必需。事实上,你已经明确地违反了它:

logger = logging.getLogger('ControllerOne')

因此,您可以通过将线程ID或名称放入记录器名称,为每个线程使用单独的名称。例如:

logger = logging.getLogger('ControllerOne.{}'.format(threading.get_ident())

或者,在您的情况下,由于您似乎每个线程都有一个唯一的task_id,您可以使用它而不是线程ID。

当然这意味着您必须实际使用记录器;你不能只是致电logging.debug。你不能依赖basicConfig;您将需要在每个线程中显式配置记录器。由于每个线程都创建了自己独立的ControllerOne实例,因此显而易见的地方是ControllerOne.__init__;在该函数中,您可以使用包含线程或任务ID的记录器名称调用getLogger,创建并设置一个FileHandler,其中还包含名称中的线程或任务ID,并将其存储为{ {1}}。然后,只要您需要记录某些内容,就可以self.logger

如果这一切听起来像gobbledegook,因为你不知道self.logger.debug(…)是什么,你可能需要至少阅读HOWTO中的basic tutorial,但是advanced tutorialcookbook也很有用。