简体   繁体   中英

How to create a non-root logger in python

I'm trying to create a non-root logger in a child python module using logging.getLogger('child'), but I'm getting an error "No handlers could be found for logger "child"

I'm trying to have a parent module log to parent log file. The parent module will create instances of the child module, and I want the child module to write its own child log file, without propagating its messages up to the parent log file.

Here's what I have for the parent module (this is executed by the user):

#!/usr/bin/env python

import logging, child

logging.basicConfig( filename='parent.log' )
logging.warning( 'test log from parent' )

c = child.run()

And here's the child module:

import logging
class run:
  def __init__(self):
    logging.basicConfig( filename = 'child.log' )
    childLogger = logging.getLogger( __name__ )
    childLogger.propagate = False
    childLogger.warning( 'this is a log from the child' )

Expected output is to have 2 files: parent.log (containing the 1 WARNING line from the parent module) and child.log (containing the one WARNING line from the child module).

Actual output is: one WARNING line (from the parent) is printed into the parent.log file, and there is no child.log file--the child log message isn't recorded anywhere.

Can you please tell me what I'm missing? TIA!

Replace

logging.basicConfig(filename='child.log')
childLogger = logging.getLogger(__name__)

in your child module with:

childLogger = logging.getLogger(__name__)
childLogger.addHandler(logging.FileHandler('child.log'))

or, alternatively, use dictConfig or fileConfig to configure logging in one place.

What's wrong with basicConfig ? From the docs:

This function does nothing if the root logger already has handlers configured for it.

So basically, your call to basicLogging in child module has no effect, since the first one (in parent module) has already configured the root logger. And by setting the child logger's propagate to false , the child's log entries don't get forwarded to the root logger, so you get the No handlers could be found... warning.

Edit

Just to elaborate on fileConfig , which allows a lot of flexibility, for your modules you could create a file called logging.ini :

[loggers]
keys=root,child

[handlers]
keys=logfile,logfile_child

[formatters]
keys=default

# loggers

[logger_root]
level=INFO
handlers=logfile

[logger_child]
level=INFO
handlers=logfile_child
qualname=child
propagate=0

# handlers

[handler_logfile]
class=FileHandler
formatter=default
args=('parent.log',)

[handler_logfile_child]
class=FileHandler
formatter=default
args=('child.log',)

# formatters

[formatter_default]
format=%(asctime)s [%(module)s:%(lineno)d] %(levelname)s %(message)s
datefmt=

Then, somewhere in your application, you would just need to call fileConfig :

import logging.config

logging.config.fileConfig('logging.ini')

This way your logging is configured in one place, which makes is easier to add additional loggers, change log levels, etc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM