astropy / ccdproc

Astropy affiliated package for reducing optical/IR CCD data
https://ccdproc.readthedocs.io
BSD 3-Clause "New" or "Revised" License
89 stars 87 forks source link

Use of root level logging interferes with other logging when imported #811

Open JuanCab opened 1 year ago

JuanCab commented 1 year ago

In essence, if we use the python logging facility, you should be careful because when you create a logging handler for a function, it seems that it is essentially forked off the root handler. Unless you remove the root handlers they remain active. This was a problem in my case because I imported the ImageFileCollection function and the moment I ran it for the first time, logging was activated including the root handler. This meant when I tried to use logging in my program, I was getting extra copies of the logging because the root handler was also responding to my logging calls.

I removed the root handlers by issuing the following:

    # Turn off root loggers that are activated by ImageFileCollection
    for handler in logging.root.handlers[:]:
        logging.root.removeHandler(handler)

I would suggest unless you are intending to use the root handlers in ccdproc that you remove them yourself when you spin up the logging. That said, if there is another suggested way to handle this situation, I would appreciate the feedback.

mwcraig commented 1 year ago

Can you please provide an example that demonstrates the problem? At first glance, at least, I'm not seeing any place in ccdproc that uses the root logger.

JuanCab commented 1 year ago

Well, here is a code that works for me (assuming test_dir points to a directory with FITS images):

import logging
from ccdproc import ImageFileCollection

print(f"There a root handler? {logging.root.hasHandlers()}")

logger=logging.getLogger("__main__")
print(f"There a root handler? {logging.root.hasHandlers()}")

ifc = ImageFileCollection("./exoplanet-project/")
print(f"There a root handler? {logging.root.hasHandlers()}")

On my system, running as the first command in ipython, I get:

There a root handler? False
There a root handler? False
There a root handler? True
JuanCab commented 1 year ago

Just for humor's sake, try setting the level of the logger you create. When I create a handler, I do all this:

logger = logging.getLogger("multi_image_photometry")
logger(logging.INFO)
console_format = logging.Formatter('%(message)s')
fh = logging.StreamHandler()
fh.setFormatter(console_format)
fh.setLevel(logging.INFO)   # Set the individual handler's response level
logger.addHandler(fh)

Not sure if that somehow decouples it from the root handler, since you are not just using the default settings (from root).