How to preserve the default sink when calling .remove()? How to remove all but the default sync when calling .remove()
Closed this issue · 4 comments
Sometimes an example is easier than an abstract description.
Starting with this simple program:
from loguru import logger
import sys
word = sys.argv[1]
log_file = f"{word}" + "_{time}" + ".log"
logger.add(log_file)
logger.debug(word)
If we run this program via python program.py hello
and then run the
program again via python program.py world
we get 2 log files, each
with exactly 1 line. 1 file will look like this:
2020-12-10 11:47:42.348 | DEBUG | __main__:<module>:12 - hello
and the other file like this:
2020-12-10 11:47:47.179 | DEBUG | main::12 - world
However, that is not what happens in our Python Spark environment
In our spark environment, successive invocations of the sample script
lead to the second log file having all the output of the first run and
the second:
2020-12-10 11:47:42.348 | DEBUG | __main__:<module>:12 - hello
2020-12-10 11:47:47.179 | DEBUG | __main__:<module>:12 - world
And then the 3rd run having the output of the 1st 2 runs in addition
to it's own. And so on and so forth.
My fix was to use .remove()
So I modified our script, similar the sample script, as follows:
import sys
from loguru import logger
word = sys.argv[1]
log_file = f"{word}" + "_{time}" + ".log"
logger.remove()
logger.add(log_file)
logger.debug(word)
In other words, I called .remove()
prior to adding the new filename,
so that it would not use previously created sinks.
But I only wanted to remove file sinks, not the default sys.stderr sink
So:
- how would I call
.remove()
so that it does not remove the
default sink? - Since there is no such documented option for
.remove()
perhaps
something is in place like getting a list of handler ids? I do not
want to keep track of created handler ids via some storage
mechanism. I would much rather a call likelogger.handlers()
and if
the length if greater than 1, then I remove all but the zeroeth element.
Well, it's not really possible to selectively remove the handlers. You need to store the id returned by logger.add()
somewhere so you can pass it to logger.remove()
later.
However in your case, I may see a simpler solution. Why not just add a stderr
sink again? This is exactly the same as the default handler.
from loguru import logger
import sys
word = sys.argv[1]
log_file = f"{word}" + "_{time}" + ".log"
logger.add(log_file)
logger.add(sys.stderr)
logger.debug(word)
You need to store the id returned by
logger.add()
somewhere so you can pass it tologger.remove()
later.
I see. How do you feel about a logger.handlers
attribute/method that returns a list of all handlers so that one can do;
for i, handler in enumerate(logger.handlers):
if i == 0: # default handler
continue
else:
logger.remove(handler.id)
But thank you for the speedy reply. I i'm sure your suggestion will work for me.
This is a suggestion that comes up from time to time. However I prefer to avoid this solution because it requires to expose the internal "handler" object. This handler has no public interface, it is essentially immutable. Using Loguru, the configuration is only done through the logger
object. I don't have a big enough reason to give access to the handler, and I prefer to keep the API minimalist.
I'm closing this issue. As discussed, I prefer not to expose the handlers.