How to disable logging on the standard error stream?

228,054

Solution 1

I found a solution for this:

logger = logging.getLogger('my-logger')
logger.propagate = False
# now if you use logger it will not log to console.

This will prevent logging from being send to the upper logger that includes the console logging.

Solution 2

I use:

logger = logging.getLogger()
logger.disabled = True
... whatever you want ...
logger.disabled = False

Solution 3

You can use:

logging.basicConfig(level=your_level)

where your_level is one of those:

'debug': logging.DEBUG,
'info': logging.INFO,
'warning': logging.WARNING,
'error': logging.ERROR,
'critical': logging.CRITICAL

So, if you set your_level to logging.CRITICAL, you will get only critical messages sent by:

logging.critical('This is a critical error message')

Setting your_level to logging.DEBUG will show all levels of logging.

For more details, please take a look at logging examples.

In the same manner to change level for each Handler use Handler.setLevel() function.

import logging
import logging.handlers

LOG_FILENAME = '/tmp/logging_rotatingfile_example.out'

# Set up a specific logger with our desired output level
my_logger = logging.getLogger('MyLogger')
my_logger.setLevel(logging.DEBUG)

# Add the log message handler to the logger
handler = logging.handlers.RotatingFileHandler(
          LOG_FILENAME, maxBytes=20, backupCount=5)

handler.setLevel(logging.CRITICAL)

my_logger.addHandler(handler)

Solution 4

Using Context manager - [ most simple ]

import logging 

class DisableLogger():
    def __enter__(self):
       logging.disable(logging.CRITICAL)
    def __exit__(self, exit_type, exit_value, exit_traceback):
       logging.disable(logging.NOTSET)

Example of use:

with DisableLogger():
    do_something()

If you need a [more COMPLEX] fine-grained solution you can look at AdvancedLogger

AdvancedLogger can be used for fine grained logging temporary modifications

How it works:
Modifications will be enabled when context_manager/decorator starts working and be reverted after

Usage:
AdvancedLogger can be used
- as decorator `@AdvancedLogger()`
- as context manager `with  AdvancedLogger():`

It has three main functions/features:
- disable loggers and it's handlers by using disable_logger= argument
- enable/change loggers and it's handlers by using enable_logger= argument
- disable specific handlers for all loggers, by using  disable_handler= argument

All features they can be used together

Use cases for AdvancedLogger

# Disable specific logger handler, for example for stripe logger disable console
AdvancedLogger(disable_logger={"stripe": "console"})
AdvancedLogger(disable_logger={"stripe": ["console", "console2"]})

# Enable/Set loggers
# Set level for "stripe" logger to 50
AdvancedLogger(enable_logger={"stripe": 50})
AdvancedLogger(enable_logger={"stripe": {"level": 50, "propagate": True}})

# Adjust already registered handlers
AdvancedLogger(enable_logger={"stripe": {"handlers": "console"}

Solution 5

(long dead question, but for future searchers)

Closer to the original poster's code/intent, this works for me under python 2.6

#!/usr/bin/python
import logging

logger = logging.getLogger() # this gets the root logger

lhStdout = logger.handlers[0]  # stdout is the only handler initially

# ... here I add my own handlers 
f = open("/tmp/debug","w")          # example handler
lh = logging.StreamHandler(f)
logger.addHandler(lh)

logger.removeHandler(lhStdout)

logger.debug("bla bla")

The gotcha I had to work out was to remove the stdout handler after adding a new one; the logger code appears to automatically re-add the stdout if no handlers are present.

IndexOutOfBound Fix: If you get a IndexOutOfBound Error while instantiating lhStdout, move the instantiation to after adding your file handler i.e.

...
logger.addHandler(lh)

lhStdout = logger.handlers[0]
logger.removeHandler(lhStdout)
Share:
228,054

Related videos on Youtube

sorin
Author by

sorin

Another geek still trying to decipher the meaning of “42”. It seems that amount his main interest are: online communities of practice and the way they evolve in time product design, simplicity in design and accessibility productivity and the way the IT solutions are impacting it

Updated on March 26, 2022

Comments

  • sorin
    sorin about 2 years

    How to disable logging on the standard error stream in Python? This does not work:

    import logging
    
    logger = logging.getLogger()
    logger.removeHandler(sys.stderr)
    logger.warning('foobar')  # emits 'foobar' on sys.stderr
    
    • Stevoisiak
      Stevoisiak about 6 years
      For those wondering why anyone would want to disable logging: You wouldn't want to log private data like passwords or API keys.
    • Mad Physicist
      Mad Physicist almost 6 years
      @StevenVascellaro. Why are those being sent to a logger in the first place then? That doesn't sound right...
    • Stevoisiak
      Stevoisiak almost 6 years
      @MadPhysicist I have an application which sends XML requests to an external API. By default, these requests are logged to a file. However, the initial login requires authentication with a username and password, which I don't want logged.
    • Mad Physicist
      Mad Physicist almost 6 years
      @StevenVascellaro. I see. Thanks for the explanation.
    • Piotr Dobrogost
      Piotr Dobrogost over 5 years
      You do not show how/where you add your handlers. If they were added to the root logger this would prevent logging from adding default StreamHandler as described at docs.python.org/3/library/logging.html#logging.basicConfig Also, per linked description, the default StreamHandler is only added during first call emitting log message so when you print logger.handlers it should be empty (as it precedes logger.debug() call). The code in question displays only [] (empty list of handlers). Verified with Python 2.7.15 and Python 3.6.6.
    • random_forest_fanatic
      random_forest_fanatic over 5 years
      @StevenM.Vascellaro Another reason for disabling logging is if a third-party package is way too verbose, and is making it hard to find the relevant logs among all the others.
  • sorin
    sorin about 14 years
    This could work if logger.handlers would be contain something, currently is [].
  • Chris
    Chris about 10 years
    I really like this idiom, but I would rather be able to disable a particular namespace. For example, I just want the root logger temporarily disabled. Although using this idiom, we should be able to just temporarily add/remove handlers and the such.
  • Pierre
    Pierre almost 10 years
    In Python 2.7+ this is available as NullHandler()
  • lsh
    lsh almost 8 years
    this also works at the logging module level to disable logging entirely, for example: import logging; logging.disable(logging.CRITICAL);: docs.python.org/2/library/logging.html#logging.disable
  • starfry
    starfry almost 7 years
    Unless I am doing something wrong, this only disables the root logger and not any created like log = logging.getLogger(__name__)
  • Joe
    Joe almost 7 years
    This is generally useful info, but the question asked how t o disable console logging, not how to add an additional handler. if you were to examine my_logger.handlers with the above code applied to the original example, you'd see two handlers -- your new file handler and the original stream handler.
  • Joe
    Joe almost 7 years
    This could be problematic if you're dealing with multiple loggers or multiple handlers. If, for example, you still want to log to a file but want to disable the stream handler in a specific case.
  • lfk
    lfk over 6 years
    I don't think this is a good solution. Not propagating to higher loggers could have other undesirable consequences.
  • Hartley Brody
    Hartley Brody over 6 years
    If you wanted to only filter message below a certain log level (say, all INFO messages), you could change the second line to something like logger.setLevel(logging.WARNING)
  • Stevoisiak
    Stevoisiak about 6 years
    How would you re-enable the log afterwards?
  • Mátray Márk
    Mátray Márk over 5 years
    This is much better than disabling propagation.
  • Piotr Dobrogost
    Piotr Dobrogost over 5 years
    The reason why this works (disables default StreamHandler) can be seen when reading description of logging.basicConfig() function (emphasis mine): Does basic configuration for the logging system by creating a StreamHandler with a default Formatter and adding it to the root logger. The functions debug(), info(), warning(), error() and critical() will call basicConfig() automatically if no handlers are defined for the root logger.docs.python.org/3/library/logging.html#logging.basicConfig
  • Piotr Dobrogost
    Piotr Dobrogost over 5 years
    Downvote as the question asks how to disable standard StreamHandler only
  • Piotr Dobrogost
    Piotr Dobrogost over 5 years
    Why are you using app.logger which you don't even specify instead of the root logger explicitly mentioned in the question (logging.getLogger()) and most answers? How do you know you can safely modify handlers property instead of calling Logger.addHandler method?
  • Piotr Dobrogost
    Piotr Dobrogost over 5 years
    This disables the root logger, and thus all the other loggers – strictly speaking disabling the root logger does not disable any other loggers. Besides the question asks about disabling default StreamHandler only.
  • Piotr Dobrogost
    Piotr Dobrogost over 5 years
    The question asks how to disable default StreamHandler only.
  • Piotr Dobrogost
    Piotr Dobrogost over 5 years
    The sequence logger = logging.getLogger(); lhStdout = logger.handlers[0] is wrong as the root logger initially has no handlers – python -c "import logging; assert not logging.getLogger().handlers". Verified with Python 2.7.15 and Python 3.6.6.
  • Piotr Dobrogost
    Piotr Dobrogost over 5 years
    Not an answer – the question asks how to disable default StreamHandler only.
  • Piotr Dobrogost
    Piotr Dobrogost over 5 years
    Not an answer as blocking propagation effectively disables all handlers of the root logger and the question clearly states (…) but I may have other handlers there that I want to keep which suggests the intention is to disable default StreamHandler of the root logger only.
  • Mathews Sunny
    Mathews Sunny over 5 years
    Add some description about the code. It would help much better
  • KristianR
    KristianR over 5 years
    You don’t need to roll your own class, you can use @contextmanager from contextlib and write a yielding function
  • Maggyero
    Maggyero about 5 years
    The disabled attribute is not part of the public API. See bugs.python.org/issue36318.
  • Maggyero
    Maggyero about 5 years
    The disabled attribute is not part of the public API. See bugs.python.org/issue36318.
  • user3504575
    user3504575 about 5 years
    If you are into exotic fruits on your pizza. Sure.
  • Nishant
    Nishant about 5 years
    CRITICAL was the word I was looking for. Thanks.
  • Not a machine
    Not a machine over 4 years
    I would love to see a debug level of OFF. It is unambiguous and simple.
  • Maggyero
    Maggyero about 4 years
    Stopping message propagation is not enough. Since Python 3.2, the logging.lastResort handler will still log messages of severity logging.WARNING and greater to sys.stderr in the absence of other handlers. See my answer.
  • pymen
    pymen over 3 years
    @PiotrDobrogost i have added a link to AdvancedLogger which allows to temporary disable output to console (StreamHandler)
  • NealWalters
    NealWalters over 3 years
    Excellent, but the question also asked how to re-enable it? For example, would you do a removeFilter and how?
  • Maggyero
    Maggyero over 3 years
    @NealWalters For the 1st solution, you would create a handler: handler = logging.NullHandler(), add it to the logger and disable propagation to disable logging: logger.addHandler(handler); logger.propagate = False, and remove it from the logger and re-enable propagation to re-enable logging: logger.removeHandler(handler); logger.propagate = True. For the 2nd solution, you would create a filter: def filter(record): return False, add it to the logger to disable logging: logger.addFilter(filter), and remove it from the logger to re-enable logging: logger.removeFilter(filter).
  • yucer
    yucer over 3 years
    should this be enclosed in try / finally ? What happens if the code rises one exception ? Does the logger remain disabled ?
  • Piotr
    Piotr over 2 years
    logging.CRITICAL+1