API Manual

Getting started

Boilerplate

After importing, you have to define one or several loggers with explicite names.

from monologue import get_logger
logger = get_logger("explicite name")

Drop in replacement for print

Instead of

print "Message I intend to convey"

use

logger.msg("Message I intend to convey")

Spit (custom) dots on demand

See the calls to logger.dot on lines 13 and 16 of this example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
def fly_to_1(x):
    """ Given x an positive integer, the loop in this function is
    believed to stop (but there is no math proof of this yet).  """

    while x != 1:

        if x % 2 == 0:  # if x is odd
            x /= 2  # halve x
        else:
            x = 3 * x + 1

        # Simplest way to indicate loops:
        logger.dot()

        # Display intermediate results:
        logger.dot(dot_string='[%d]' % x)

Set an alternate char or string for use as dot

Normally, you’d get plain dots:

for i in xrange(5):
    logger.dot()

gives:

.....

whereas

logger.set_dot_str("x")
for i in xrange(5):
    logger.dot()

gives:

xxxxx

Mixing dots and messages

Of course you can mix dots and informative messages. This code

for x in xrange(10):
    logger.dot()
    if x == 5:
        logger.msg("x is 5!")

produces the following output:

xxxxxx
[explicite name] x is 5!
xxxx

More in depth

Automatic progress notification (with dots and messages)

You can delegate the count of iterations to the logger. For instance, let’s rewrite fly_to_1.

# Configure: a dot every 10 steps
logger.dot_every(10)

# Configure: progress message every 100 steps
logger.progress_every(100)

# Optional: reset the number of iterations
logger.progress_reset()

while x != 1:

    # count one step
    logger.step()

    if x % 2 == 0:  # if x is odd
        x /= 2  # halve x
    else:
        x = 3 * x + 1

logger.complete()

If you know how many batches you are going to handle, you can even provide the user with progress percentages.

Logger creation, fetching and configuration

Logger uniqueness

Alike to the Python logging API, loggers are created or fetched upon a call to get_logger (getLogger in logging). Unique loggers are identified with their names, and parametrized upon creation, ie the first call to get_logger with a given name.

Here, a and b identify the same object:

a = get_logger("name")
b = get_logger("name")

Caveat: no reparametrization upon further calls to get_logger

Many caracteristics of a logger can be configured upon the creation of a logger, by using optional keywords when calling get_logger; however, later calls with a given logger name will only return a reference to a previously created logger.

It may be a good practice to use different thematic loggers, with different names, in different source files, or even in functions.

Specify log files (including stdout)

monologue can log to arbitrary places.

logfile keyword of get_logger

If no logfile keyword is specified to the first call to get_logger with a given name, the output defaults to sys.stdout, making monologue a drop-in replacement for print.

logfile can be either:

  • a file handler open for writing
  • a filename, that will be open in append mode.
add_logfile method of ProgressAndLog

Partial log: messages or dots only

Add a timestamp to messages

Lazy formatting of messages

This is a feature of logging: a message that is not displayed because its importance does not match the verbosity of the logger will not be formatted at all. In order to benefit from this optimization, replace

logger.msg("This message is about %s" % subject)

by

logger.msg("This message is about %s", msgvars=subject)

or

logger.msg("This %(adjective)s message is about %(subject)s" %
    {'adjective': 'dumb', 'subject': subject})

by

logger.msg("This %(adjective)s message is about %(subject)s",
    msgvars={'adjective': 'dumb', 'subject': subject})

Verbosity control

Verbosity (criticity) of a message
Verbosity threshold of a logger