2

I want to create a function that works like the build-in print function in Python:

print 'test', i, 'started'

So a call like this should work:

log('test', i, 'started)

The log function should call the logging.info() function (from the Python logging module). How can I create such a function?

This is my first try:

import logging
def log(*args):
    logging.info(args)

log('test', i, 'started)

But the output is not what I want:

('test', 2, 'started')

While it should be:

test 2 started
0

7 Answers 7

7

This works:

def log(*args):
    logging.info(' '.join(map(str, args)))
Sign up to request clarification or add additional context in comments.

Comments

3

You can do this kind of thing:

def log(*args):
  logging.info(' '.join(args))

4 Comments

I'm looking for a solution that calls logging.info().
beware that if args contains non-strings (as it does in the question), this will cause an exception. compie's answer, or logging.info(' '.join([str(x) for x in args])) work better.
@dcrosta : +1 for pointing that out, -1 for using the list comprehension instead of a generator ;)
@Stephen oops -- force of habit.
1

How about:

def log(*args):
    logging.info(' '.join([str(arg) for arg in args]))

HTH!

1 Comment

the extra list comprehension has not been necessary for a while now (2.4). ' '.join(str(arg) for arg in args) should suffice.
1

Define a function that takes a variable number of arguments, you can operate on the parameter list args to print it how you'd like:

>>> def log(*args):
...   print args

>>> log("a", 1, "b")
("a", 1, "b")

Or:

>>> def log(*args):
...   for a in args:  # <- loop over the arguments
...     print a,   # <- notice the comma that says "no newline".
...   print        # <- force a newline after the log statement.

>>> log("a", 1, "b")
a 1 b

If you want to use logging.info:

logging.info(msg[, *args[, **kwargs]])

Logs a message with level INFO on the root logger. The arguments are interpreted as for debug().

>>> def log(*args):
...   logging.info(" ".join("%s" %a for a in args))

Comments

1

I do this, to make it accept a format string. Coming from a C world, I like my format strings. I use code exactly like this in several production systems.

def logf(fmt, *args):
    try: m = fmt % args
    except:
        # Catch mismatch between fmt/args; prevents logging.info from
        # failing below, as well.
        m = fmt
        fmt = "%s"
    if DEBUG:
        stderr.write("[%s] %s\n" % (time.asctime(), m))
    logging.info(fmt, *args)

Usage:

logf("There are %u entries in the list, and my mood is %s.", len(L), "sad")
logf("It works without arguments, as well")
logf("Test %d started", i)

Call me old-school, I guess. This is all Python 2, by the way - 3 is far different.

Comments

0

The logging methods require a format-string as the first argument (or, as some others have suggested, a literal string to log). You can easily generate a format string for a given-number of arguments with code something like this:

def log(*args):
    fmt_string = ' '.join(['%s'] * len(args))
    logging.info(fmt_string, *args)

This works because the multiplication operator on lists is defined to extend the list with copies of the list's contents.

Note that I'm passing *args as the second "argument" to logging.info -- this is Python's syntax for expanding a sequence (args will be a tuple, I believe) into a series of positional arguments in the function call.

1 Comment

simply logging ' '.join(args) as "format string" would be easier. or maybe ' '.join(str(a) for a in args).
0

One day I was reading the python docs and I came across the functools.partial() method (or I read about it somewhere -- I can't remember). A little playing around led to the following code I now put at the beginning of every python script I write:

import sys, functools

nl = "\n"

def StreamOut(stream, *s, **kw):
    k = kw.setdefault
    # Process keyword arguments
    sep     = k("sep", "")
    auto_nl = k("auto_nl", True)
    prefix  = k("prefix", "")
    convert = k("convert", str)
    # Convert position arguments to strings
    strings = map(convert, s)
    # Dump them to the stream
    stream.write(prefix + sep.join(strings))
    # Add a newline if desired
    if auto_nl:
        stream.write(nl)

out  = functools.partial(StreamOut, sys.stdout)
outs = functools.partial(StreamOut, sys.stdout, sep=" ")
dbg  = functools.partial(StreamOut, sys.stdout, sep=" ", prefix="+ ")
err  = functools.partial(StreamOut, sys.stderr)

out("Hi there", "how are you?")
outs("Hi there", "how are you?")

Put it into a file and try them out. This makes for some easily-extendible functions.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.