Hello!
I have been very appreciated to use loguru where a friend of mine has showed me and its been what I have been looking for in ages!
I have some issues with it and I wouldn't say its a bug or so, maybe a new feature or something I might have missed?
What I have done is super simple script such as:
from loguru import logger
logger.info("hello world")
and I tried to run it with something called PM2 which looks like this:

The only issue is that it marks it as a "error" with the red line which shouldn't. How is when I change it to a normal print:
print("hello world")

So my question is simple as, is it possible to do something similar where logger.info would mark it as a "green" success color in the pm2 while exception/debug could be red?
As I mentioned, its probably maybe not an issue but maybe a cool feature for those who uses pm2 and if there is anything I can help you out, please let me know! :)
Hello!
The only difference between logger.info() and print() is that the former writes on sys.stderr while the later writes on sys.stdout. I guess this explains why you're seeing different colors.
It's possible to configure the logger so that it writes to stdout, simply remove the default handler first:
logger.remove()
logger.add(sys.stdout)
However in such case, errors and debug will be colored in green too. So there are two solutions. You can either use a custom sink that will choose where to write the output depending on the log level:
def pm2_sink(message):
if message.record["level"].name == "INFO":
sys.stdout.write(message)
else:
sys.stderr.write(message)
logger.remove()
logger.add(pm2_sink)
Or you can use two sinks with a filter:
logger.remove()
logger.add(sys.stdout, filter=lambda record: record["level"].name == "INFO")
logger.add(sys.stderr, filter=lambda record: record["level"].name != "INFO")
Hello!
The only difference between
logger.info()andprint()is that the former writes onsys.stderrwhile the later writes onsys.stdout. I guess this explains why you're seeing different colors.It's possible to configure the
loggerso that it writes tostdout, simply remove the default handler first:logger.remove() logger.add(sys.stdout)However in such case, errors and debug will be colored in green too. So there are two solutions. You can either use a custom sink that will choose where to write the output depending on the log level:
def pm2_sink(message): if message.record["level"].name == "INFO": sys.stdout.write(message) else: sys.stderr.write(message) logger.remove() logger.add(pm2_sink)Or you can use two sinks with a
filter:logger.remove() logger.add(sys.stdout, filter=lambda record: record["level"].name == "INFO") logger.add(sys.stderr, filter=lambda record: record["level"].name != "INFO")
Hello! Appreciate the answer which I did a quick test and it seems to work! In that case it would be better to wrap it to a wrapper if I am going to use it in multiple scripts at the same time.
However my knowledge is not good enough to know how to wrap the logger to a wrapper :'( But however the solution you gave me seem to work. I just need to figure out myself how to fix the wrapper
How do you imagine such a wrapper?
If you want to repetitively use such configuration, you can indeed export it to another file. Then, if you import the file it will automatically configure the logger right?
Also, note that you can use the logger across multiple modules without needing to re-configure it (because it's always the same logger object).
How do you imagine such a wrapper?
If you want to repetitively use such configuration, you can indeed export it to another file. Then, if you import the file it will automatically configure the
loggerright?Also, note that you can use the
loggeracross multiple modules without needing to re-configure it (because it's always the sameloggerobject).
Yupp I just realized that about the multiple modules. It worked very well and it was not much that needed to be configured with was really nice! Appreciate the help! Have a wonderful day!
Was giving advise to @BarryThrill in a side channel, this is what we came up with:
shunt the pm2 sink & logger configuration to a module, that executes the necessary loguru configuration calls on import.
this has two major effects:
Specifically we shunted it to the package's top-level __init__.py, so it executes on startup as a natural result of executing anything under the package via -m.
This does have the unfortunate side effect of working too well, im not sure we can do an entry-point check on __init__.py to prevent the logger reconfiguration if the project is imported by something else; though in this application thats not important (as its not a library).
Thanks for the write-up!
Usually I would configure the logger inside an if __name__ == "__main__" block in case the app is used as a library. However, as you call .remove() before .add(), even if the module happens to be re-imported for some reason, it should not be noticeable.
Glad you found a solution. I wish a good day to both of you too. :+1:
Most helpful comment
Thanks for the write-up!
Usually I would configure the
loggerinside anif __name__ == "__main__"block in case the app is used as a library. However, as you call.remove()before.add(), even if the module happens to be re-imported for some reason, it should not be noticeable.Glad you found a solution. I wish a good day to both of you too. :+1: