1

Elapsed time in loguru is a datetime.timedelta object. (loguru docs)

I want the time to be formatted as minutes and seconds. So, if elapsed.seconds = 123, it would become 2m3s.
This would normally be attainable by {elapsed.seconds//60}m{elapsed.seconds%60}s in an f-string or using .format().

But if I use f-string in loguru's format argument string, it obviously does not recognise the variable elapsed.seconds as that belongs to loguru and not the current scope. And so it gives the error AttributeError: 'datetime.timedelta' object has no attribute 'seconds//60' in case of f-strings and NameError: name 'elapsed' is not defined in case of trying to use .format() Here's the code to replicate-

from loguru import logger

logger_format = ('{time:DD-MMM-YYYY HH:mm:ss}'
                  '|{level:<8}| '
                  '({elapsed.seconds}s)')

logger.add('test.log', delay=True, format=logger_format, level='DEBUG')

def print_something(x):
    if type(x) == int:
        print(x)
        logger.debug('Printing int')
        
print_something(2)

Here's the log it could print if running time was 123s:

07-Jul-2022 18:20:19|DEBUG   | (123s) Printing int

Here's the log I want it to print:

07-Jul-2022 18:20:19|DEBUG   | (2m3s) Printing int
callmeanythingyouwant
  • 1,789
  • 4
  • 15
  • 40

1 Answers1

1

The format argument can be a format string, but it can also be a callable that takes a record dictionary and returns a string, like so:

from loguru import logger

def my_format(record):
    mins = record['elapsed'].seconds // 60
    secs = record['elapsed'].seconds % 60
    return '|{level:<8}| ({mins}m{secs}s)\n{exception}'.format(**record, mins=mins, secs=secs)

logger.add('test.log', delay=True, format=my_format, level='DEBUG')

You could also use an f-string if you prefer.

Wander Nauta
  • 18,832
  • 1
  • 45
  • 62
  • Works fine! Strangely enough though, the logs do not get printed if there is no newline character included in the return value string. This is not the case when the passed argument is just a string and not callable. Also, the `{file}` keyword gives an error when ran from a jupyter notebook. It was not giving an error when a string was passed instead of a callable. Nonetheless, it's a great solution. – callmeanythingyouwant Jul 08 '22 at 12:26