3

When using Python logging library, standard approach is just to write some message like this:

logging.info("All right")

But sometimes it necessary to show result status of some (long) task (after a while after output of main part of the message). For example:

Some long computing...    [done]

or

Some long computing...    [fail]

How can I solve this problem?

TOTAL:

Ok. It is possible, but only in the next line. For output success message in the same line you must use other tool (probably, custom), not logging Python library.

user1051870
  • 913
  • 1
  • 10
  • 21

5 Answers5

2

It sounds like this might help you out.

import logging

logging.basicConfig(format = "%(asctime)s - %(levelname)s - %(message)s", 
                    level = logging.DEBUG)

logging.info("Long Task is starting")
try:
    StartLongTaskFunction()
    logging.info("Long task finished")
except:
    logging.exception("Long task failed")

Note that logging.exception() is slightly different from logging.error(). After the log entry is added for logging.exception(), the entire Python error message is included as well.

If you want to log critical events in StartLongTaskFunction, you can insert log entries inside this function as well. Even if you import this function from a separate module, you can still reference the same log file.

Michael David Watson
  • 3,028
  • 22
  • 36
  • Better, but what about displaying success message in the same line with basic message? – user1051870 May 02 '13 at 15:47
  • What do you mean by 'basic message' and 'success message'? – Michael David Watson May 02 '13 at 15:52
  • As kll pointed out below, logging in Python is line oriented. If you have multiple data points that you want to log, you need to store them in a variable/object within your script and enter them all into the same log entry. It is not natively supported in logging to retroactively update a previously entered log entry. – Michael David Watson May 02 '13 at 17:55
2

Logging isn't meant to be used as a progress UI ... your program should work the same way whether or not logging is configured and even when the verbosity is set to minimum. If you want to print something to the console, use print rather than logging.

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

Could you please try as below? Actually I could not understand your exactly problem.

#!/usr/bin/python

status_success = "Done"
status_fail = "Fail"

import logging
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)
"""
Do some computation here and based on that result display the below message
"""
logging.info('Some long computation [%s]' % status_success)

Or

logging.info('Some long computation [%s]' % status_fail)
Mogsdad
  • 44,709
  • 21
  • 151
  • 275
gsmaker
  • 533
  • 1
  • 4
  • 21
  • Ok. I just specify my question. Problem is when you have some LONG computation and it necessary to display first part of message long before second part. – user1051870 May 02 '13 at 14:01
1

The obvious solution would be to only log the line after you know if your process succeeded or not. I take it by your question though that you want to provide the user with some output to make it apparent that your computing process is working.

As far I know, it is not possible to do what you want using the python logging module as it is in its very nature line oriented. Imagine you would be sending this to a syslog server, how would the server understand that these two text messages belong together? The server would, in addition, need to keep state, which in general is something we don't want.

Either abandon the logging module in preference of simple print statements or log after the computing is done.

print "Some long computation...",
res = compute()
print "res"
kll
  • 111
  • 4
0

While you can do this with printing (see Print in one line dynamically) you can't do it with logging, as others have said.

However, my solution is a very simple context manager:

import contextlib

@contextlib.contextmanager
def log_context(logger, message):
    try:
        yield
        logger.log(logging.INFO, f'{message} [done]')
    except Exception:
        logger.log(logging.WARNING, f'{message} [fail]')
        raise

You can use this as follows:

log = logging.getLogger(__name__)
with log_context(log, 'Slow function...'):
   very_slow_function(42)

and this will log something like either

[INFO] Slow function... [done]

or

[WARNING] Slow function... [fail]

if very_slow_function raises any exception.

supermitch
  • 2,062
  • 4
  • 22
  • 28