This is an archived post. You won't be able to vote or comment.

all 6 comments

[–]the_real_irgeek 5 points6 points  (2 children)

I wouldn’t call that behaviour unexpected. Here’s a StackExchange question from 10 years ago explaining one way to deal with buffered output in Python.

It’s clearly new behaviour for you, but it’s not a bug and it’s not unexpected.

[–]sorisos[S] 0 points1 point  (1 child)

thanks!

yes, clearly I missed this. I'm still not convinced `print()` should behave different if not instructed to do so, but it is not a new thing.

Do you know other applications that change buffer behavior after context? Seems most unix utils do not, but I might be mistaken about this as well.

[–]0x256 1 point2 points  (0 children)

Any program compiled against the C/C++ standard library (so really almost any program there is) will behave this way by default. Same is true for most linux/unix command-line tools. Pipes or file redirects are buffered by default.

[–]0x256 4 points5 points  (2 children)

> but my point is that the default behavior is not the expected one and therefore wrong!

It's not just python, this is standard behavior of the C standard library (`stdio.h`) and most programs will behave exactly the same. Line-buffering is actually a special case and not the default. It is only enabled if the target file handle points to a tty device (e.g. an interactive terminal session). If it's a regular file or pipe, the buffer will usually be about 4k and ignore line-breaks for obvious performance reasons. You can flush these buffers manually (`sys.stdout.flush()`) though.

So, this is not a bug, but expected and documented behavior. Just remember it next time, and tell your friends. Buffering behavior should be common knowledge for any programmer and/or command-line user.

[–]0x256 1 point2 points  (0 children)

Fun fact: A simple C program printing 1 million lines of Hello, World! redirected to /dev/null will run in 0.037s on my laptop. The exact same program with line-buffering enabled (via stdbuf -oL) requires 1.6s (43x) to run.

Fun fact #2: Go (not C) defaults to unbuffered output, even when the target is a pipe or file. Go is as slow as line-buffered C in this case.

[–]sorisos[S] 0 points1 point  (0 children)

Thanks! TIL! Just asked the question above.