5

I am using .setFormatter() to set the same logging.Formatter() on each of my handlers.

Is there a way to set a global default format?

Alternatively - is it possible to iterate though the handlers already added via .addHandler() to a logger ?

Another question mentions what the format is, but not how to set it.

WoJ
  • 27,165
  • 48
  • 180
  • 345
  • 1
    Set the format on the global logger and nowhere else. – Mad Physicist Oct 03 '17 at 15:38
  • 1
    You can iterate through the list in the `handlers` attribute of a logger. – Mad Physicist Oct 03 '17 at 15:39
  • @MadPhysicist: thanks. I managed to iterate over the `handlers` in my logger. If you would not mind to turn the comment into an answer I would gladly accept it. I did not understand the first comment, though (about a "global logger" -- what is that? Do you mean the logger received via `getLogger()`? it does not have a `setFormatter()` method) – WoJ Oct 03 '17 at 15:52
  • Yes, when you call it without a name. I guess it's technically called root logger, not global logger. – Mad Physicist Oct 03 '17 at 15:54

2 Answers2

4

The intended way is to attach the formatter to each handler as you're creating them.

Since you're supposed to set up logging destinations in one, central place at the start of the main program, this isn't so taxing to do.

E.g. this is the stock logging set-up code that I use in my scripts that are to be run autonomously:

# set up logging #####################################
import sys,logging,logging.handlers,os.path
log_file=os.path.splitext(__file__)[0]+".log"
l = logging.getLogger()
l.setLevel(logging.DEBUG)
f = logging.Formatter('%(asctime)s %(process)d:%(thread)d %(name)s %(levelname)-8s %(message)s')
h=logging.StreamHandler(sys.stdout)
h.setLevel(logging.NOTSET)
h.setFormatter(f)
l.addHandler(h)
h=logging.handlers.RotatingFileHandler(log_file,maxBytes=1024**2,backupCount=1)
h.setLevel(logging.NOTSET)
h.setFormatter(f)
l.addHandler(h)
del h,f
#hook to log unhandled exceptions
def excepthook(type,value,traceback):
    logging.error("Unhandled exception occured",exc_info=(type,value,traceback))
    #Don't need another copy of traceback on stderr
    if old_excepthook!=sys.__excepthook__:
        old_excepthook(type,value,traceback)
old_excepthook = sys.excepthook
sys.excepthook = excepthook
del excepthook,log_file
# ####################################################

There are other methods but each has a downside:

  • Each logger has an undocumented <logger>.handlers list, but it only lists handlers connected to that logger directly. So, you need to iterate over this list for all loggers you have if you have multiple.
  • There is a global undocumented logging._handlerList (references to all handlers are kept there to shut them down at exit). Likewise, that is an implementation detail.
  • Finally, you can override a handler's init logic by

    • replacing __init__ methods of Handler and/or subclass (that will affect everything else that uses logging), or by
    • subclassing/addin a mixin to the required classes.

    That is probably an overkill.

ivan_pozdeev
  • 33,874
  • 19
  • 107
  • 152
1

If you have a number of handlers, you're advised to configure logging using the logging.config.dictConfig() API. This other answer shows how to configure formatters for handlers; you may be able to adapt it to your needs.

Vinay Sajip
  • 95,872
  • 14
  • 179
  • 191