Does `print()` delay in some consoles where `stdout.flush` doesn't?

Question:

I’m working on an open source python library that uses a verbose_print command to log outputs in the console. Currently it looks like this:

def sys_write_flush(s):
    """ Writes and flushes without delay a text in the console """
    sys.stdout.write(s)
    sys.stdout.flush()


def verbose_print(verbose, s):
    """ Only prints s (with sys_write_flush) if verbose is True."""
    if verbose:
        sys_write_flush(s)

I proposed a change that looks like this:

def verbose_print(verbose, *args):
    """ Prints everything passed except the first argument if verbose is True."""
    if verbose:
        print(*args)

Apart from the fact that it fails on Python 2 (bonus point for fixing this!), I thought that this would be better and more idiomatic. The advantages are, that you can treat verbose_print exactly like print, except that the first argument has to be True or False.

The repo owner replied with this message:

I should have documented this one, but basically the issue was that in
some consoles (and in the IPython notebook, at least at the time),
"print" commands get delayed, while stdout.flush are instantaneous, so
my method was better at providing feedback.

I would be against changing it to print unless it solves some known
issues.

Is this still a valid concern? Would print() followed by sys.stdout.flush() avoid the delay? Are there any better ways to write this?

Source

Asked By: Tom Burrows

||

Answers:

Quote from the docs:

print evaluates each expression in turn and writes the resulting
object to standard output.

Standard output is defined as the file object named stdout in the
built-in module sys. If no such object exists, or if it does not
have a write() method, a RuntimeError exception is raised.

According to this, print writes to sys.stdout, so, yes, doing a sys.stdout.flush() after printing will have the same effect as flushing after sys.stdout.write-ing.


The syntax print(*a) fails in Python 2 because print isn’t a function, but a statement, and that fun(*stuff) construct is only applicable to functions.

In Python 3 print(*a) passes whatever a contains to the function print as separate arguments, but this is equal to passing a big string:

separator = ' '
print separator.join(map(str, iterable))

So, your code could look like this:

def verbose_print(verbose, *args):
    """ Prints everything passed except the first argument if verbose is True."""
    if verbose:
        print " ".join(map(str, args))
        sys.stdout.flush()

Although I don’t see why this can be faster or more readable than the original.

Answered By: ForceBru
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.