TL;DR
INDEX = 0
#: change to new file location
logger.handlers[INDEX].setStream( open('/path/to/new/log/file.log', 'a') )
#: change to stdout or stderr
import sys
logger.handlers[INDEX].setStream( sys.stdout ) # or sys.stderr
#: change to another device
logger.handlers[INDEX].setStream( open('/dev/ttys010', 'a') )
- after registering a
logging.FileHandler
to your logger, you can reach into its internals and change the stream it outputs to "on the fly".
- make sure
INDEX
accesses the right handler within the logger. if you only added a FileHandler
, then it should be index 0
.
Explained
Well first, following the logging documentation's suggested idiom, you would get a new logger instance named after the __name__
of whatever your specific package, module, class, or function:
#: class
>>> class A:
def __init__(self):
self.logger = logging.getLogger(self.__class__.__name__)
>>>A().logger
<Logger A (WARNING)>
#: function
>>> def func():
logger = logging.getLogger(func.__name__)
print(logger)
>>> func()
<Logger func (WARNING)>
#: module
>>> logger = logging.getLogger( __name__ )
>>> logger
<Logger __main__ (WARNING)>
#: package (e.g. a package named 'pkg', write this in '__init__.py')
>>> logger = logging.getLogger( __package__ )
>>> logger
<RootLogger pkg (WARNING)>
Next, if you've registered a logging.FileHandler
handler for your logger, like so:
logger.addHandler( logging.FileHandler('/tmp/logfile.log', 'a') )
then you can you can change the file it outputs to by replacing the stream it outputs to:
INDEX = 0 # you will have to find the index position of the `FileHandler` you
# registered to this logger. I justed listed them with: `logger.handlers`
# and picked the one I needed. if you only register one handler
# then it should be at index 0, i.e the first one
#: change to new file location
logger.handlers[INDEX].setStream( open('/path/to/new/log/file.log', 'a') )
#: change to stdout or stderr
import sys
logger.handlers[INDEX].setStream( sys.stdout ) # or sys.stderr
#: change to another device
logger.handlers[INDEX].setStream( open('/dev/ttys010', 'a') )
If your curious, found this in a few minutes, by doing a bit of digging like so (in ipython
and python
interpreters):
>>> import logging
>>> logger = logging.getLogger( __name__ )
>>> logger.addHandler( logging.FileHandler('/tmp/logfile', 'a') )
>>> globals()
>>> dir(logger)
#: found that the logger has 'handlers' attribute
>>> dir(logger.handlers)
>>> logger.handlers
#: found that the FileHandler I registered earlier is at index: 0
>>> logger.handlers[0]
>>> dir(logger.handlers[0])
#: found that FileHandler has a dictionary '__dict__'
>>> logger.handlers[0].__dict__
#: found that FileHandler dict has 'baseFilename' attribute with the filename
#: i had set when registering the file handler
>>> logger.handlers[0].__dict__['baseFilename']
#: tried changing the file it points to
>>> logger.handlers[0].__dict__['baseFilename'] = '/tmp/logfile.log'
#: tried logging
>>> logger.info(f'hello world')
#: didn't work
#: found another interesting perhaps relevant attribute 'stream' in the
#: FileHandler dict
>>> logger.handlers[0].__dict__['stream']
>>> dir(logger.handlers[0].__dict__['stream'])
>>> logger.handlers[0].__dict__['stream'].__dict__
#: tried replacing the stream altogether
>>> logger.handlers[0].__dict__['stream'] = open('/tmp/logfile.log','a')
#: tried logging
>>> logger.info(f'hello world again')
#: it worked
>>> logger.info(f'hey it worked')
#: found another interesting perhaps relevant method 'setStream'
>>> logger.handlers[0].setStream( open('/tmp/otherlogfile.log','a') )
#: tried logging
>>> logger.info(f'hello world again')
#: it worked
>>> logger.info(f'hey it worked')