After importing, you have to define one or several loggers with explicite names.
from monologue import get_logger
logger = get_logger("explicite name")
Instead of
print "Message I intend to convey"
use
logger.msg("Message I intend to convey")
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)
|
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
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
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.
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")
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.
monologue can log to arbitrary places.
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:
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})