例如,我有这些文件包含我想要使用的类(仅示例,可能不起作用)
# 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。
答案 0 :(得分:6)
记录器名称(传递给getLogger
函数的字符串)可以是您想要的任何内容。正如the docs解释:
name
可能是一个以句点分隔的层次结构值,例如foo.bar.baz
(例如,它也可能只是普通foo
)。在分层列表中较低的记录器是列表中较高的记录器的子项。例如,给定名称为foo
的记录器,名称为foo.bar
,foo.bar.baz
和foo.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 tutorial和cookbook也很有用。