Tensorflow suppresses logging messages bug - python

Tensorflow makes logging messages hide and not appear when I run the code.
I have tried the following stuff but couldn't find a way to make my code work.
import logging
logger = tf.get_logger()
logger.setLevel(logging.ERROR)
import os
import tensorflow as tf
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
So my code is the following
import logging
import tensorflow as tf
logging.basicConfig(filename='example.log', level=logging.DEBUG)
logging.debug('This message should go to the log file')
logging.info('So should this')
logging.warning('And this, too')
I expected to have the debug messages into my file example.log but nothing appeared inside example log.
When I import tensorflow, the messages don't appear and when I don't they do.
I need to use both tensorflow and logging because I use an existing code. Is there a way so logging suppresses Tensorflow?

Two facts:
logging.basicConfig will do nothing if the root logger is already configured:
This function does nothing if the root logger already has handlers configured for it.
tensorflow has the absl-py dependency that will try to initialize logging when imported by appending a NullHandler to the root handler:
# The absl handler will always be attached to root, not the absl logger.
if not logging.root.handlers:
# Attach the absl handler at import time when there are no other handlers.
# Otherwise it means users have explicitly configured logging, and the absl
# handler will only be attached later in app.run(). For App Engine apps,
# the absl handler is not used.
logging.root.addHandler(_absl_handler)
Not sure why the handler is attached to the root logger instead of the absl logger, though - might be a bug or a workaround for some other issue.
So the problem is that the import tensorflow call will call import absl.logging which causes an early logger configuration. The subsequent call (yours) to logging.basicConfig will hence do nothing. To fix that, you need to configure logging before importing tensorflow:
import logging
logging.basicConfig(filename='example.log', level=logging.DEBUG)
import tensorflow as tf
logging.debug('This message should go to the log file')
logging.info('So should this')
logging.warning('And this, too')
Rule of thumb: always call your logging configuration as early as possible.
Writing logs in default format to file
If you just want to write the default logs to file, abseil logger can also do that:
from absl import logging as absl_logging
absl_logging.get_absl_handler().use_absl_log_file(
program_name='mytool',
log_dir='/var/logs/'
)

Besides the method offered by #hoefling, you can also clear the handlers of the root logger just before your logging configurations:
logging.getLogger().handlers = []
# ...
logging.basicConfig(level=level, handlers=handlers)

Related

Python logging with multiple module imports

I'm trying to establish logging in all modules I'm using. My project structure is
# driver.py
import logging
logger = logging.getLogger(__name__)
class driver:
....
# driver_wrapper.py
from driver import driver
device = driver(...)
def driver_func():
logging.info("...")
....
# main.py
import logging
import driver_wrapper
logging.basicConfig(stream=sys.stdout, level=logging.WARNING)
driver_wrapper.driver_func()
My problem now is that I still get INFO level messages and also the output is 'INFO:root'. But I would expect the module name instead of root.
Is there a way to set the logging level in the main.py for all modules or is it already correct how I do it? There are a lot of posts about this problem but the solutions don't seem to work for me.
All your modules that use logging should have the logger = logging.getLogger(__name__) line, and thereafter you always log to e.g.logger.info(...), and never call e.g. logging.info(...). The latter is equivalent to logging to the root logger, not the module's logger. That "all your modules" includes driver_wrapper.py in your example.

Python loggers not inheriting level from root logger

I know this question has been asked like a million times before, but I just don't know why this:
import logging
from mylib import MyClass
hdlr = logging.FileHandler("MyLog.log", encoding="utf-16", mode="w")
hdlr.setFormatter(
logging.Formatter("[%(levelname)s] %(name)s <%(module)s.%(funcName)s> %(message)s")
)
hdlr.setLevel(logging.DEBUG)
myobj = MyClass(handlers=[hdlr])
where myclass.py which defines MyClass looks like this:
import logging
logger = logging.getLogger("MyClass")
class MyClass:
def __init__(self, handlers):
for hdlr in handlers:
logging.root.addHandler(hdlr)
This only outputs WARNING messages in the file.
I read this question and I verified that I am not doing any logging before adding the handlers to root logger.
However replacing this line,
hdlr.setLevel(logging.DEBUG)
to this:
logging.root.setLevel(logging.DEBUG)
works, when it apparently (jump to the EDIT) shouldn't?
Some background info: MyClass is a library I am working on. Its root __init__.py contains no logging code, (although I think libraries should have some logging related code in that file).
It doesn't matter what the level of the handler is, if the message never makes it to the handler. By default, the root logger level is WARN; it won't dispatch INFO or DEBUG messages to any handlers. When you set the root logger to DEBUG, it will send DEBUG messages to handler(s), which then can decide what to do with them based on their level settings.
Related to logging | error() gets sent to FileHandler... but not other Logging Levels

Disable logging.basicConfig from imported module

I'm trying to import from the following module:
https://github.com/dmlc/gluon-cv/blob/master/gluoncv/torch/data/gluoncv_motion_dataset/dataset.py
However this includes the lines:
logging.basicConfig(level=logging.INFO)
log = logging.getLogger()
Which is messing up the logging settings I'm trying to apply in my main file. How can I import from this module, but overwrite the above log settings?

How to enable logging for requests_oauthlib?

I'm trying to enable logging to stdout for requests_oauthlib. The example in the docs suggests this:
# Uncomment for detailed oauthlib logs
#import logging
#import sys
#log = logging.getLogger('oauthlib')
#log.addHandler(logging.StreamHandler(sys.stdout))
#log.setLevel(logging.DEBUG)
But it doesn't seem to have any effect. What's the proper way to do it?
The root logger's name should be requests_oauthlib, i.e. the package name. The modules in the package define loggers like this
logger = logging.getLogger(__name__)
so configuring the root logger as described in the example should work:
import logging
import sys
log = logging.getLogger('requests_oauthlib')
log.addHandler(logging.StreamHandler(sys.stdout))
log.setLevel(logging.DEBUG)

How to turn sqlalchemy logging off completely

sqlalchemy is keep loggin to console even I have the following code
import logging
logger = logging.getLogger()
logger.disabled = True
How to turn off sqlalchemy's logging completely?
Did you pass echo=True to create_engine()? By default it creates StreamHandler which outputs to console. As documentation says, if you didn't provide any echo=True arguments and didn't configure root sqlalchemy logger, it will not log anything.
You can turn off the sqlalchemy logger using:
import logging
logging.basicConfig()
logging.getLogger('sqlalchemy').setLevel(logging.ERROR)
For more info, see the docs.
A more drastic solution:
import logging
logging.disable(logging.WARNING)

Categories

Resources