How can I create my own log instance for each thread?

For example, I have these files with classes that I want to use (just an example may not work)


import logging

logger = logging.getLogger('HelperOne')

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

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




import logging

from helper_one import HelperOne

logger = logging.getLogger('ControllerOne')

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

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

        ho = HelperOne( + '_data')


And I have a file that creates Threads

import logging 

from controller_one import ControllerOne

# this function creates threads (its just an example)
def run_task(task_id, data):
        filename=os.path.join('logs', str(task_id) + '.log'),

    result = ControllerOne(data)

    logging.debug('run_task: ' + result)


If I create a log instance like in my example, the entire log is written to one file. How can I create its own logging instance for each thread, logging its own file?

Best regards, Alex.


source to share

1 answer

The registrar name (the string passed to the function getLogger

) can be whatever you want. As the docs explain:


- a potentially hierarchical meaning separated by a period, for example

(although it could also be just simple foo

, for example) Registrars that are lower in the hierarchical list are children of the registrars higher in the list. For example, when registering a registrar with a name, foo

registrars with names


and foo.bam

are descendants foo

. The log name hierarchy is similar to and identical to the Python package hierarchy if you organize the loggers on a per module basis using the recommended construction logging.getLogger(__name__)

. That's because in module __name__

is the name of modules in the Python package namespace.

So, using __name__

as a name is recommended, but not required. And in fact you are already explicitly breaking this:

logger = logging.getLogger('ControllerOne')


So, you can just use a separate name for each thread by putting the thread id or name in the log name. For example:

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


Or, in your case, since you seem to have a unique one task_id

for each thread, you can simply use that instead of the thread id.

Of course, this means that you must actually use a registrar; you cannot just call logging.debug

. And you cannot rely on basicConfig

; you will need to explicitly configure the logger on each thread. Since each thread creates its own independent instance ControllerOne

, the obvious place to do this is in ControllerOne.__init__

; in this function you can call getLogger

with the name of the log that includes the thread or task id, create and set FileHandler

, which also includes the thread or the task id in the name and save it as self.logger

. Then when you need to record something, you just do self.logger.debug(…)


If this all sounds like gobbledegook to you because you don't know what it is FileHandler

, you probably need to read at least a basic tutorial in the HOWTO, but the advanced tutorial and cookbook are very helpful too.



All Articles